Skip to content

Commit

Permalink
feat(geom): update bounds() to support opt. margin
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jun 20, 2022
1 parent f74e377 commit 8cdc372
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 30 deletions.
71 changes: 45 additions & 26 deletions packages/geom/src/bounds.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MultiFn1 } from "@thi.ng/defmulti";
import type { MultiFn1O } from "@thi.ng/defmulti";
import { defmulti } from "@thi.ng/defmulti/defmulti";
import type { AABBLike, IShape, PathSegment, PCLike } from "@thi.ng/geom-api";
import { bounds as arcBounds } from "@thi.ng/geom-arc/bounds";
Expand All @@ -9,14 +9,14 @@ import { comp } from "@thi.ng/transducers/comp";
import { filter } from "@thi.ng/transducers/filter";
import { iterator1 } from "@thi.ng/transducers/iterator";
import { map } from "@thi.ng/transducers/map";
import { addN2 } from "@thi.ng/vectors/addn";
import { max } from "@thi.ng/vectors/max";
import { min } from "@thi.ng/vectors/min";
import { mul2 } from "@thi.ng/vectors/mul";
import { mulN2 } from "@thi.ng/vectors/muln";
import { set2 } from "@thi.ng/vectors/set";
import { sub2 } from "@thi.ng/vectors/sub";
import { subN2 } from "@thi.ng/vectors/subn";
import { aabbFromMinMax } from "./aabb.js";
import { aabbFromMinMaxWithMargin } from "./aabb.js";
import type { Arc } from "./api/arc.js";
import type { Circle } from "./api/circle.js";
import type { Cubic } from "./api/cubic.js";
Expand All @@ -29,10 +29,11 @@ import { Rect } from "./api/rect.js";
import type { Text } from "./api/text.js";
import { __collBounds } from "./internal/bounds.js";
import { __dispatch } from "./internal/dispatch.js";
import { rectFromMinMax } from "./rect.js";
import { rectFromMinMaxWithMargin } from "./rect.js";

export const bounds: MultiFn1<IShape, AABBLike | undefined> = defmulti<
export const bounds: MultiFn1O<IShape, number, AABBLike | undefined> = defmulti<
any,
number | undefined,
AABBLike | undefined
>(
__dispatch,
Expand All @@ -45,29 +46,38 @@ export const bounds: MultiFn1<IShape, AABBLike | undefined> = defmulti<
tri: "points",
},
{
arc: ($: Arc) =>
rectFromMinMax(...arcBounds($.pos, $.r, $.axis, $.start, $.end)),
arc: ($: Arc, margin = 0) =>
rectFromMinMaxWithMargin(
...arcBounds($.pos, $.r, $.axis, $.start, $.end),
margin
),

circle: ($: Circle) =>
new Rect(subN2([], $.pos, $.r), mulN2(null, [2, 2], $.r)),
circle: ($: Circle, margin = 0) =>
new Rect(
subN2([], $.pos, $.r + margin),
mulN2(null, [2, 2], $.r + margin)
),

cubic: ({ points }: Cubic) =>
rectFromMinMax(
...cubicBounds(points[0], points[1], points[2], points[3])
cubic: ({ points }: Cubic, margin = 0) =>
rectFromMinMaxWithMargin(
...cubicBounds(points[0], points[1], points[2], points[3]),
margin
),

ellipse: ($: Ellipse) =>
new Rect(sub2([], $.pos, $.r), mul2(null, [2, 2], $.r)),
ellipse: ($: Ellipse, margin = 0) => {
const r = addN2([], $.r, margin);
return new Rect(sub2([], $.pos, r), mul2(null, [2, 2], r));
},

group: ($: Group) => {
group: ($: Group, margin = 0) => {
const res = __collBounds($.children, bounds);
return res ? new Rect(...res) : undefined;
return res ? new Rect(...res).offset(margin) : undefined;
},

line: ({ points: [a, b] }: Line) =>
rectFromMinMax(min([], a, b), max([], a, b)),
line: ({ points: [a, b] }: Line, margin = 0) =>
rectFromMinMaxWithMargin(min([], a, b), max([], a, b), margin),

path: (path: Path) => {
path: (path: Path, margin = 0) => {
const b = __collBounds(
[
...iterator1(
Expand All @@ -80,18 +90,27 @@ export const bounds: MultiFn1<IShape, AABBLike | undefined> = defmulti<
],
bounds
);
return b ? new Rect(...b) : undefined;
return b ? new Rect(...b).offset(margin) : undefined;
},

points: ($: PCLike) => rectFromMinMax(...bounds2($.points)),
points: ($: PCLike, margin = 0) =>
rectFromMinMaxWithMargin(...bounds2($.points), margin),

points3: ($: PCLike) => aabbFromMinMax(...bounds3($.points)),
points3: ($: PCLike, margin = 0) =>
aabbFromMinMaxWithMargin(...bounds3($.points), margin),

quadratic: ({ points }: Quadratic) =>
rectFromMinMax(...quadraticBounds(points[0], points[1], points[2])),
quadratic: ({ points }: Quadratic, margin = 0) =>
rectFromMinMaxWithMargin(
...quadraticBounds(points[0], points[1], points[2]),
margin
),

rect: ($: IShape) => <AABBLike>$.copy(),
rect: ($: IShape, margin = 0) =>
margin === 0
? <AABBLike>$.copy()
: (<AABBLike>$.copy()).offset(margin),

text: ($: Text) => new Rect(set2([], $.pos), [0, 0]),
text: ($: Text, margin = 0) =>
new Rect(subN2([], $.pos, margin), [0, 0]), // TODO
}
);
8 changes: 4 additions & 4 deletions packages/geom/src/internal/bounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { min } from "@thi.ng/vectors/min";
import { sub } from "@thi.ng/vectors/sub";

/**
* Computes the total bounds for the given shape collection, which
* should either contain only 2D or 3D types. No mixed dimensions are
* allowed! Currently the {@link bounds} function MUST be passed in as
* arg to avoid circular module dependencies.
* Computes the total bounds for the given shape collection, which should either
* contain only 2D or 3D types. No mixed dimensions are allowed! Currently the
* {@link bounds} function MUST be passed in as arg to avoid circular module
* dependencies. Returns 2-tuple of `[pos, size]`.
*
* @param shapes - input shapes
* @param bounds - bbox function
Expand Down

0 comments on commit 8cdc372

Please sign in to comment.