-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getBoundingBox improvements #121
Changes from 7 commits
2c5ceb6
f321922
e2fffb3
71c1b09
2d4cd22
22424a3
fd34f48
fee735d
5944849
7629547
90643d9
d3c40ed
11d629c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
function Tracker(path) { | ||
this.trackee = path; | ||
this.group = new Group().addTo(path.parent); | ||
this.box = new Rect(0, 0, 1000, 1000).addTo(this.group).stroke('#000', 2); | ||
this.vert1 = new Path().addTo(this.group).moveTo(0, 0).lineTo(0, 1000).stroke('#F00', 2); | ||
this.vert2 = new Path().addTo(this.group).moveTo(0, 0).lineTo(0, 1000).stroke('#F00', 2); | ||
this.horz1 = new Path().addTo(this.group).moveTo(0, 0).lineTo(1000, 0).stroke('#00F', 2); | ||
this.horz2 = new Path().addTo(this.group).moveTo(0, 0).lineTo(1000, 0).stroke('#00F', 2); | ||
stage.on('advance', this, this.track); | ||
} | ||
|
||
Tracker.prototype = { | ||
track: function() { | ||
var box = this.trackee.getBoundingBox( this.trackee.attr('matrix') ); | ||
this.vert1.attr('x', box.left); | ||
this.vert2.attr('x', box.right); | ||
this.horz1.attr('y', box.top); | ||
this.horz2.attr('y', box.bottom); | ||
} | ||
} | ||
|
||
var star = new Path.star(100, 100, 50, 5, 3); | ||
|
||
star.fill('yellow').stroke('black', 1); | ||
star.addTo(stage); | ||
new Tracker(star); | ||
|
||
anim(); | ||
|
||
|
||
function anim() { | ||
star.morphTo( | ||
new Path.star( | ||
Math.random() * 400 + 200, | ||
Math.random() * 400 + 200, | ||
Math.random() * 80 + 20, | ||
0 | Math.random() * 5 + 5, | ||
Math.random() * 3 + .2 | ||
).fill('random').stroke('random', 1).attr('rotation', Math.random() * Math.PI*2), | ||
'2s', | ||
{ | ||
onEnd: anim, | ||
easing: 'sineInOut' | ||
} | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -229,53 +229,49 @@ define([ | |
return this; | ||
}, | ||
|
||
getComputed: function(key) { | ||
/** | ||
* Computes bounding boxes and single data points of a display object. | ||
* | ||
* @param {String} key What to compute. One of "top", "right", "bottom", | ||
* "left", "width" and "height" | ||
* @param {Matrix} [transform=null] A transform to apply to all points | ||
* before computation. | ||
* @return {Object} | ||
*/ | ||
getBoundingBox: function(transform) { | ||
|
||
var children = this.displayList.children; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if there are no children, the The code for empty objects already lives in Adding a guard here should do the trick. if (!children.length) {
return DisplayObject.prototype.getBoundingBox.call(this, transform);
} And a unit test for this special case might be handy |
||
var isOffsetKey = | ||
key === 'top' || | ||
key === 'right' || | ||
key === 'bottom' || | ||
key === 'left'; | ||
|
||
if (isOffsetKey) { | ||
var attributeName = (key === 'top' || key === 'bottom') ? 'y' : 'x'; | ||
var compare = (key === 'top' || key === 'left') ? min : max; | ||
|
||
return tools.reduce(children, function(current, child, i) { | ||
var childValue = child.attr(attributeName) + child.getComputed(key); | ||
if (i === 0) { | ||
return childValue; | ||
} | ||
return compare(current, childValue); | ||
}, 0); | ||
} else { | ||
var size = tools.reduce(children, function(size, child, i) { | ||
var childSize = child.getComputed('size'); | ||
var childX = child.attr('x'); | ||
var childY = child.attr('y'); | ||
|
||
var isFirst = i === 0; | ||
var size = tools.reduce(children, function(size, child, i) { | ||
var childMatrix = child.attr('matrix').clone(); | ||
var childSize = child.getBoundingBox( | ||
transform ? childMatrix.concat(transform) : childMatrix | ||
); | ||
var childX = child.attr('x'); | ||
var childY = child.attr('y'); | ||
childX = childY = 0; | ||
|
||
var childTop = childY + childSize.top; | ||
size.top = isFirst ? childTop : min(size.top, childTop); | ||
var isFirst = i === 0; | ||
|
||
var childRight = childX + childSize.right; | ||
size.right = isFirst ? childRight : max(size.right, childRight); | ||
var childTop = childY + childSize.top; | ||
size.top = isFirst ? childTop : min(size.top, childTop); | ||
|
||
var childBottom = childY + childSize.bottom; | ||
size.bottom = isFirst ? childBottom : max(size.bottom, childBottom); | ||
var childRight = childX + childSize.right; | ||
size.right = isFirst ? childRight : max(size.right, childRight); | ||
|
||
var childLeft = childX + childSize.left; | ||
size.left = isFirst ? childLeft : min(size.left, childLeft); | ||
var childBottom = childY + childSize.bottom; | ||
size.bottom = isFirst ? childBottom : max(size.bottom, childBottom); | ||
|
||
return size; | ||
}, {top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0}); | ||
var childLeft = childX + childSize.left; | ||
size.left = isFirst ? childLeft : min(size.left, childLeft); | ||
|
||
size.height = size.bottom - size.top; | ||
size.width = size.right - size.left; | ||
return size; | ||
}, {top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0}); | ||
|
||
return key === 'size' ? size : size[key]; | ||
} | ||
size.height = size.bottom - size.top; | ||
size.width = size.right - size.left; | ||
|
||
return size; | ||
}, | ||
getIndexOfChild: function(displayObject) { | ||
return this.displayList.children.indexOf(displayObject); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -570,6 +570,51 @@ define([ | |
return curvedSegments; | ||
}; | ||
|
||
/** | ||
* Calculates the potential bounds of a single cubic bezier curve | ||
* @param {Array} p0 The starting point of the curve in the form [x, y] | ||
* @param {Array} curve A curveTo segment (e.g. `['curveTo',n,n,n,n,n,n]`) | ||
*/ | ||
CurvedPath.getPotentialBoundsOfCurve = function(p0x, p0y, cp1x, cp1y, cp2x, cp2y, p1x, p1y) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is potential about the returned bounds? |
||
|
||
var p0 = [p0x, p0y]; | ||
var p1 = [cp1x, cp1y]; | ||
var p2 = [cp2x, cp2y]; | ||
var p3 = [p1x, p1y]; | ||
var bounds = [[], []]; | ||
|
||
bounds[0].push(p3[0]); | ||
bounds[1].push(p3[1]); | ||
|
||
for (var i = 0; i < 2; ++i) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a URL that points to the origin of this approach and if possible add some comments? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the worst part of the implementation because I am not sure how it works. I ported it from a python script I found here: http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html I tried understanding the math on the article you linked to but in the end, after struggling, I grabbed this and ported it and it seemed to work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @padolsey please add his MIT License note to our LICENSE file. |
||
var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; | ||
var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; | ||
var c = 3 * p1[i] - 3 * p0[i]; | ||
if (a == 0) { | ||
if (b == 0) continue; | ||
var t = -c / b; | ||
if (0 < t && t < 1) bounds[i].push(f(t)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. semicolon and brackets are missing |
||
continue; | ||
} | ||
var b2ac = Math.pow(b, 2) - 4 * c * a; | ||
if (b2ac < 0) continue; | ||
var t1 = (-b + Math.sqrt(b2ac))/(2 * a); | ||
if (0 < t1 && t1 < 1) bounds[i].push(f(t1)); | ||
var t2 = (-b - Math.sqrt(b2ac))/(2 * a); | ||
if (0 < t2 && t2 < 1) bounds[i].push(f(t2)); | ||
} | ||
|
||
// Return bounds in the form `[ xBoundsArray, yBoundsArray ]` | ||
return bounds; | ||
|
||
function f(t) { | ||
return Math.pow(1-t, 3) * p0[i] | ||
+ 3 * Math.pow(1-t, 2) * t * p1[i] | ||
+ 3 * (1-t) * Math.pow(t, 2) * p2[i] | ||
+ Math.pow(t, 3) * p3[i]; | ||
} | ||
}; | ||
|
||
CurvedPath.fromArc = function(x1, y1, rx, ry, angle, large, sweep, x2, y2) { | ||
|
||
// If the endpoints (x1, y1) and (x2, y2) are identical, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc block still has the
key
parameter