Skip to content

Commit 9625ab6

Browse files
committed
feat: add utils for bounds sepaeation
1 parent a4ed897 commit 9625ab6

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vutils",
5+
"comment": "feat: add utils for bounds within separation",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vutils"
10+
}

packages/vutils/src/data-structure/bounds.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { isArray } from '../common';
2-
import { isRotateAABBIntersect } from '../graphics';
2+
import { isRotateAABBIntersect, rotatePoint } from '../graphics';
33
import type { vec4, vec8 } from '../math';
44
import { abs, epsilon } from '../math';
55
import type { IMatrix } from './matrix';
@@ -78,6 +78,7 @@ export type IAABBBounds = IBounds;
7878

7979
export interface IOBBBounds extends IBounds {
8080
angle: number;
81+
getRotatedBounds: () => IBoundsLike;
8182
}
8283

8384
export function transformBoundsWithMatrix(out: IBounds, bounds: IBounds, matrix: IMatrix): IBounds {
@@ -441,4 +442,24 @@ export class OBBBounds extends Bounds {
441442
clone(): OBBBounds {
442443
return new OBBBounds(this);
443444
}
445+
446+
getRotatedBounds(): IBoundsLike {
447+
const cx = (this.x1 + this.x2) / 2;
448+
const cy = (this.y1 + this.y2) / 2;
449+
450+
const originPoint = { x: cx, y: cy };
451+
const corners = [
452+
rotatePoint({ x: this.x1, y: this.y1 }, this.angle, originPoint),
453+
rotatePoint({ x: this.x2, y: this.y1 }, this.angle, originPoint),
454+
rotatePoint({ x: this.x1, y: this.y2 }, this.angle, originPoint),
455+
rotatePoint({ x: this.x2, y: this.y2 }, this.angle, originPoint)
456+
];
457+
458+
const minX = Math.min(...corners.map(p => p.x));
459+
const maxX = Math.max(...corners.map(p => p.x));
460+
const minY = Math.min(...corners.map(p => p.y));
461+
const maxY = Math.max(...corners.map(p => p.y));
462+
463+
return { x1: minX, x2: maxX, y1: minY, y2: maxY };
464+
}
444465
}

packages/vutils/src/graphics/bounds-util.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { IBoundsLike } from '../data-structure';
1+
import type { IBoundsLike, IOBBBounds } from '../data-structure';
22

33
export type InsideBoundsAnchorType = 'inside' | 'inside-top' | 'inside-bottom' | 'inside-left' | 'inside-right';
44

@@ -62,3 +62,21 @@ export const calculateAnchorOfBounds = (bounds: IBoundsLike, anchorType: string)
6262

6363
return { x: anchorX, y: anchorY };
6464
};
65+
66+
export const isAABBWithinSeparation = (a: IBoundsLike, b: IBoundsLike, sep: number = 0) => {
67+
const s = Math.max(b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2);
68+
return sep > s;
69+
};
70+
71+
export const isOBBWithinSeparation = (a: IOBBBounds, b: IOBBBounds, sep: number = 0) => {
72+
if (sep === 0) {
73+
return a.intersects(b);
74+
} else {
75+
const boundsA = a.getRotatedBounds();
76+
const boundsB = b.getRotatedBounds();
77+
const horizontal = Math.max(0, boundsA.x1 > boundsB.x2 ? boundsA.x1 - boundsB.x2 : boundsB.x1 - boundsA.x2);
78+
const vertical = Math.max(0, boundsA.y1 > boundsB.y2 ? boundsA.y1 - boundsB.y2 : boundsB.y1 - boundsA.y2);
79+
80+
return sep > Math.max(horizontal, vertical);
81+
}
82+
};

0 commit comments

Comments
 (0)