Skip to content

Commit 1e270fa

Browse files
feat(geom): update intersects(), add line-group support
- add line-group impl - refactor/simplify ray-group impl
1 parent 843788f commit 1e270fa

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

packages/geom/src/intersects.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { isNumber } from "@thi.ng/checks/is-number";
21
import type { MultiFn2O } from "@thi.ng/defmulti";
32
import { defmulti } from "@thi.ng/defmulti/defmulti";
43
import type { IShape, IntersectionResult, PCLike } from "@thi.ng/geom-api";
@@ -17,13 +16,18 @@ import {
1716
import { intersectRayAABB, intersectRayRect } from "@thi.ng/geom-isec/ray-rect";
1817
import { testRectCircle } from "@thi.ng/geom-isec/rect-circle";
1918
import { testAabbAabb, testRectRect } from "@thi.ng/geom-isec/rect-rect";
20-
import { dist2, type Vec } from "@thi.ng/vectors";
19+
import type { Vec } from "@thi.ng/vectors";
20+
import { dist2 } from "@thi.ng/vectors/dist";
21+
import { distSq2 } from "@thi.ng/vectors/distsq";
22+
import { magSq2 } from "@thi.ng/vectors/magsq";
23+
import { normalize2 } from "@thi.ng/vectors/normalize";
24+
import { sub2 } from "@thi.ng/vectors/sub";
2125
import type { AABB } from "./api/aabb.js";
2226
import type { Circle } from "./api/circle.js";
2327
import type { Group } from "./api/group.js";
2428
import type { Line } from "./api/line.js";
2529
import type { Plane } from "./api/plane.js";
26-
import type { Ray } from "./api/ray.js";
30+
import { Ray } from "./api/ray.js";
2731
import type { Rect } from "./api/rect.js";
2832
import type { Sphere } from "./api/sphere.js";
2933
import { __dispatch2 } from "./internal/dispatch.js";
@@ -43,6 +47,7 @@ export interface IntersectOpts {
4347
* Currently supported pairs:
4448
*
4549
* - {@link Circle} / {@link Circle}
50+
* - {@link Line} / {@link Group}
4651
* - {@link Line} / {@link Line}
4752
* - {@link Line} / {@link Polygon}
4853
* - {@link Line} / {@link Polyline}
@@ -96,6 +101,27 @@ export const intersects: MultiFn2O<
96101
"circle-circle": (a: Circle, b: Circle) =>
97102
intersectCircleCircle(a.pos, b.pos, a.r, b.r),
98103

104+
"line-group": (
105+
{ points: [a, b] }: Line,
106+
group: Group,
107+
opts?: Partial<IntersectOpts>
108+
) => {
109+
const dir = sub2([], b, a);
110+
const max = magSq2(dir);
111+
const res = intersects(
112+
new Ray(a, normalize2(null, dir)),
113+
group,
114+
opts
115+
);
116+
if (res === NONE) return res;
117+
res.isec = res.isec!.filter((p) => distSq2(a, p) <= max);
118+
if (res.isec.length) {
119+
res.alpha = dist2(a, res.isec![0]);
120+
return res;
121+
}
122+
return NONE;
123+
},
124+
99125
"line-line": ({ points: a }: Line, { points: b }: Line) =>
100126
intersectLineLine(a[0], a[1], b[0], b[1]),
101127

@@ -114,22 +140,26 @@ export const intersects: MultiFn2O<
114140
"ray-circle": (ray: Ray, sphere: Sphere) =>
115141
intersectRayCircle(ray.pos, ray.dir, sphere.pos, sphere.r),
116142

117-
"ray-group": (ray: Ray, { children }: Group, opts?: IntersectOpts) => {
143+
"ray-group": (
144+
ray: Ray,
145+
{ children }: Group,
146+
opts?: Partial<IntersectOpts>
147+
) => {
118148
let minD = Infinity;
119149
const points: Vec[] = [];
120150
const all = opts?.all;
151+
let inside = false;
121152
for (let child of children) {
122153
let $res = intersects(ray, child, opts);
123154
if ($res.type !== IntersectionType.INTERSECT) continue;
124-
const single = isNumber($res.isec![0]);
125-
const first = single ? <Vec>$res.isec : (<Vec[]>$res.isec)[0];
155+
if ($res.inside) inside = true;
156+
const first = $res.isec![0];
126157
const alpha =
127158
$res.alpha !== undefined
128159
? $res.alpha
129160
: dist2(ray.pos, first);
130161
if (all) {
131-
if (single) points.push(first);
132-
else points.push(...(<Vec[]>$res.isec));
162+
points.push(...$res.isec!);
133163
minD = Math.min(minD, alpha);
134164
} else if (alpha < minD) {
135165
minD = alpha;
@@ -141,6 +171,7 @@ export const intersects: MultiFn2O<
141171
type: IntersectionType.INTERSECT,
142172
isec: points,
143173
alpha: minD,
174+
inside,
144175
}
145176
: NONE;
146177
},

0 commit comments

Comments
 (0)