Skip to content

Commit

Permalink
Fix/hide overlap (#3666)
Browse files Browse the repository at this point in the history
* fix(label): only consider interaction between valid box when layouting

* fix(label): fix NaN return for coline points when cal centroid

* test(label): add test case for isInteract and getPolygonCentroid

* refactor(util): tidy code of graphics

* fix(collision-detect): fix -Infinity
  • Loading branch information
pearmini committed Oct 11, 2021
1 parent 6731383 commit 339a3dc
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 5 deletions.
14 changes: 12 additions & 2 deletions src/util/collision-detect.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { vec2 } from '@antv/matrix-util';
import { isNumber } from '@antv/util';
import { vec2 } from '@antv/matrix-util';
import { BBox, Point } from '../dependents';

const { dot } = vec2;
type Vec2 = [number, number];


type Box = Pick<BBox, 'x' | 'y' | 'width' | 'height'> & { rotation?: number };

/**
Expand Down Expand Up @@ -98,6 +98,14 @@ function isProjectionOverlap(projection1: Projection, projection2: Projection):
return projection1.max > projection2.min && projection1.min < projection2.max;
}

function isValidNumber(d: number) {
return isNumber(d) && !Number.isNaN(d) && d !== Infinity && d !== -Infinity;
}

function isValidBox(box: Box) {
return Object.values(box).every(isValidNumber);
}

/**
* 快速判断两个无旋转矩形是否遮挡
*/
Expand All @@ -117,6 +125,8 @@ export function isIntersectRect(box1: Box, box2: Box, margin: number = 0): boole
* - 原理: 分离轴定律
*/
export function isIntersect(box1: Box, box2: Box) {
// 如果两个 box 中有一个是不合法的 box,也就是不会被渲染出来的,那么它们就不相交。
if (!isValidBox(box1) || !isValidBox(box2)) return false;

// 如果两个矩形没有旋转,使用快速判断
if (!box1.rotation && !box2.rotation) {
Expand Down
25 changes: 22 additions & 3 deletions src/util/graphics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BBox } from '@antv/g-svg';
import { each, isEmpty, isNumber, isNumberEqual } from '@antv/util';
import { each, isEmpty, isNumber, isNumberEqual, max, min } from '@antv/util';
import { Coordinate, IShape, Point } from '../dependents';
import { ShapeInfo } from '../interface';

Expand Down Expand Up @@ -30,6 +30,14 @@ function getPointsBox(points) {
};
}

function uniqueValues<T = number>(array: T[]) {
return Array.from(new Set(array)).length === 1;
}

function mid(array: number[]) {
return (min(array) + max(array)) / 2;
}

/**
* @ignore
* 根据弧度计算极坐标系下的坐标点
Expand Down Expand Up @@ -183,14 +191,25 @@ export function getPolygonCentroid(xs: number | number[], ys: number | number[])
// 普通色块图,xs 和 ys 是数值
return [xs, ys];
}

xs = xs as number[];
ys = ys as number[];
// 当这个 polygon 的点在一条线上的时候
// 也就是说 xs 里面的值都相同,比如:[1, 1, 1, 1]
// 或者说 ys 里面的值都相同,比如:[0, 0, 0, 0]
// 下面计算得到的 k = 0
// 导致返回的值是 [NaN, NaN]
// 所以这里做相应的处理
if (uniqueValues(xs) || uniqueValues(ys)) return [mid(xs), mid(ys)];

let i = -1;
let x = 0;
let y = 0;
let former;
let current = (xs as number[]).length - 1;
let current = xs.length - 1;
let diff;
let k = 0;
while (++i < (xs as number[]).length) {
while (++i < xs.length) {
former = current;
current = i;
k += diff = xs[former] * ys[current] - xs[current] * ys[former];
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/util/collision-detect-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,49 @@ describe('collision-detect', () => {
expect(isIntersect(getBox(rect0), getBox(rect1))).not.toBeFalsy();
});

it('isInteract 只会判断合法的 box', () => {
const b0 = {
x: 0,
y: 0,
width: 10,
height: 10,
};

const b1 = {
x: NaN,
y: NaN,
width: 10,
height: 10,
};

const b2 = {
x: Infinity,
y: Infinity,
width: 10,
height: 10,
};

const b3 = {
x: undefined,
y: undefined,
width: 10,
height: 10,
};

const b4 = {
x: -Infinity,
y: -Infinity,
width: 10,
height: 10,
};

expect(isIntersect(b0, b1)).toBe(false);
expect(isIntersect(b0, b2)).toBe(false);
expect(isIntersect(b0, b3)).toBe(false);
expect(isIntersect(b1, b2)).toBe(false);
expect(isIntersect(b0, b4)).toBe(false);
});

afterAll(() => {
rectShape.remove(true);
rect0.remove(true);
Expand Down
18 changes: 18 additions & 0 deletions tests/unit/util/graphics-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { getPolygonCentroid } from '../../../src/util/graphics';

describe('test getPolygonCentroid', () => {
test('getPolygonCentroid can handle colline points', () => {
const x1 = [1, 1, 1, 1];
const y1 = [0, 3, 4, 2];

expect(getPolygonCentroid(x1, y1)).toEqual([1, 2]);

const x2 = y1;
const y2 = x1;
expect(getPolygonCentroid(x2, y2)).toEqual([2, 1]);

const x3 = x1;
const y3 = x1;
expect(getPolygonCentroid(x3, y3)).toEqual([1, 1]);
});
});

0 comments on commit 339a3dc

Please sign in to comment.