fix #994: Revert commit b5af47a7b1

Revert back to correct implementation of Path#getArea() and implement unit tests for it.
This commit is contained in:
Jürg Lehni 2016-02-26 12:58:50 +01:00
parent 27badf58f3
commit 69c34707e7
2 changed files with 37 additions and 24 deletions

View file

@ -756,26 +756,17 @@ statics: /** @lends Curve */{
},
getArea: function(v) {
// This is a combination of the methods to decide if a path is clockwise
// and to calculate the area, as described here:
// http://objectmix.com/graphics/133553-area-closed-bezier-curve.html
// http://stackoverflow.com/questions/1165647
// We treat the curve points and handles as the outline of a polygon of
// which we determine the orientation using the method of calculating
// the sum over the edges. This will work even with non-convex polygons,
// telling you whether it's mostly clockwise.
// With bezier curves, the trick appears to be to calculate edge sum
// with half the handles' lengths, and then:
// area = 6 * edge-sum / 10
var p1x = v[0], p1y = v[1],
p2x = v[6], p2y = v[7],
h1x = (v[2] + p1x) / 2,
h1y = (v[3] + p1y) / 2,
h2x = (v[4] + v[6]) / 2,
h2y = (v[5] + v[7]) / 2;
return 6 * ((p1x - h1x) * (h1y + p1y)
+ (h1x - h2x) * (h2y + h1y)
+ (h2x - p2x) * (p2y + h2y)) / 10;
c1x = v[2], c1y = v[3],
c2x = v[4], c2y = v[5],
p2x = v[6], p2y = v[7];
return (3.0 * c1y * p1x - 1.5 * c1y * c2x
- 1.5 * c1y * p2x - 3.0 * p1y * c1x
- 1.5 * p1y * c2x - 0.5 * p1y * p2x
+ 1.5 * c2y * p1x + 1.5 * c2y * c1x
- 3.0 * c2y * p2x + 0.5 * p2y * p1x
+ 1.5 * p2y * c1x + 3.0 * p2y * c2x) / 10;
},
getBounds: function(v) {

View file

@ -14,15 +14,37 @@ QUnit.module('Path');
test('path.length', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74))
new Segment([121, 334], [-19, 38], [30.7666015625, -61.53369140625]),
new Segment([248, 320], [-42, -74], [42, 74])
]);
var length = path.length;
equals(length, 172.10112809179614, 'path.length');
equals(function() {
return path.length;
}, 172.10112809179614);
var t = path.curves[0].getTimeAt(length / 4);
equals(t, 0.2255849553116685, 'path.curves[0].getTimeAt(length / 4)');
equals(function() {
return path.curves[0].getTimeAt(path.length / 4);
}, 0.2255849553116685);
});
test('path.area', function() {
var rect = new Path.Rectangle({
point: [0, 0],
size: [10, 10]
});
equals(function() {
return rect.area;
}, 100);
var circle = new Path.Circle({
center: [0, 0],
radius: 10
});
equals(function() {
return circle.area;
}, Math.PI * 100, null, { tolerance: 0.1 });
});
test('curve.getTimeAt() with straight curve', function() {