Skip to content
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

fix(g-canvas): bbox calculation should be correct for path with arc #224

Merged
merged 1 commit into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/g-canvas/__tests__/bugs/issue-202-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('#202', () => {
height: 500,
});

it.only('the transformation from canvas coordinates to relative coordinates should be effective', (done) => {
it('the transformation from canvas coordinates to relative coordinates should be effective', (done) => {
const group = canvas.addGroup();
const circle = group.addShape('circle', {
attrs: {
Expand Down
54 changes: 54 additions & 0 deletions packages/g-canvas/tests/bugs/issue-222-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const expect = require('chai').expect;
import Canvas from '../../src/canvas';

const dom = document.createElement('div');
document.body.appendChild(dom);
dom.id = 'c1';

describe('#187', () => {
const canvas = new Canvas({
container: dom,
width: 600,
height: 600,
localRefresh: true, // 由于局部刷新依赖于图形的包围盒计算,因此测试时 localRefresh 需要为 true
});

it('bbox calculation should be correct for path with arc', () => {
const shape1 = canvas.addShape('path', {
attrs: {
fill: '#1890ff',
path: [
['M', 227.31794680557064, 200.00000266808433],
['L', 87.61525298763183, 98.50004569833794],
['A', 172.6820363488079, 172.6820363488079, 0, 0, 0, 63.08757910043951, 253.36168385505405],
['L', 227.31794680557064, 200.00000266808433],
['Z'],
],
},
});
const shape2 = canvas.addShape('path', {
attrs: {
fill: '#5D7092',
fillOpacity: 0.85,
lineWidth: 0,
path: [
['M', 227.31796092753956, 200.00000629398966],
['L', 63.08757910043951, 253.36168385505405],
['A', 172.68203634880794, 172.68203634880794, 0, 0, 0, 345.526943245539, 325.8797870175248],
['L', 227.31796092753956, 200.00000629398966],
['z'],
],
},
});
const bbox1 = shape1.getBBox();
const bbox2 = shape2.getBBox();
expect(bbox1.minX).eqls(54.63591866828193);
expect(bbox1.minY).eqls(98.50004569833794);
expect(bbox1.maxX).eqls(227.31794680557064);
expect(bbox1.maxY).eqls(253.36168385505414);
expect(bbox2.minX).eqls(63.087579100439484);
expect(bbox2.minY).eqls(200.00000629398966);
expect(bbox2.maxX).eqls(345.526943245539);
expect(bbox2.maxY).eqls(372.68203634880797);
});
});
20 changes: 16 additions & 4 deletions packages/g-math/src/arc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,14 @@ export default {
const xs = [startAngle, endAngle];
for (let i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
const xAngle = xDim + i;
if (startAngle < xAngle && xAngle < endAngle) {
xs.push(xAngle);
if (startAngle < endAngle) {
if (startAngle < xAngle && xAngle < endAngle) {
xs.push(xAngle);
}
} else {
if (endAngle < xAngle && xAngle < startAngle) {
xs.push(xAngle);
}
}
}

Expand All @@ -93,8 +99,14 @@ export default {
const ys = [startAngle, endAngle];
for (let i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
const yAngle = yDim + i;
if (startAngle < yAngle && yAngle < endAngle) {
ys.push(yAngle);
if (startAngle < endAngle) {
if (startAngle < yAngle && yAngle < endAngle) {
ys.push(yAngle);
}
} else {
if (endAngle < yAngle && yAngle < startAngle) {
ys.push(yAngle);
}
}
}

Expand Down
42 changes: 42 additions & 0 deletions packages/g-math/tests/unit/ellipse-arc-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,48 @@ describe('ellipse arc test', () => {
expect(box.width).eqls(p11.x - p21.x);
});

it('box, ellipse 0 when startAngle > endAngle', () => {
// 1 / 2 圆弧,旋转 0
const xRotation = 0;
const box = arc.box(100, 100, 20, 10, xRotation, Math.PI, 0);
const p1 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 0);
const p2 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 1);
const p11 = rotation({ x: 100, y: 100 }, p1, xRotation);
const p21 = rotation({ x: 100, y: 100 }, p2, xRotation);

ctx.beginPath();
ctx.ellipse(100, 100, 20, 10, xRotation, 0, Math.PI);
ctx.stroke();

ctx.beginPath();
ctx.strokeRect(box.x, box.y, box.width, box.height);
expect(box.x).eqls(p11.x);
expect(box.y).eqls(p11.y);
expect(box.width).eqls(p21.x - p11.x);
expect(box.height).eqls(10);
});

it('box, ellipse 90 when startAngle > endAngle', () => {
// 1 / 2 圆弧,旋转 90
const xRotation = Math.PI / 2;
const box = arc.box(100, 100, 20, 10, xRotation, Math.PI, 0);
const p1 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 0);
const p2 = arc.pointAt(100, 100, 20, 10, 0, Math.PI, 0, 1);
const p11 = rotation({ x: 100, y: 100 }, p1, xRotation);
const p21 = rotation({ x: 100, y: 100 }, p2, xRotation);

ctx.beginPath();
ctx.ellipse(100, 100, 20, 10, xRotation, 0, Math.PI);
ctx.stroke();

ctx.beginPath();
ctx.strokeRect(box.x, box.y, box.width, box.height);
expect(box.x).eqls(p21.x - 10);
expect(box.y).eqls(p11.y);
expect(box.width).eqls(10);
expect(box.height).eqls(40);
});

it('tangent angle', () => {
expect(arc.tangentAngle(0, 0, 10, 10, 0, 0, Math.PI, 0)).eqls(Math.PI / 2);
expect(arc.tangentAngle(0, 0, 10, 10, 0, 0, Math.PI, 1)).eqls(Math.PI / 2 + Math.PI);
Expand Down