Skip to content

Commit

Permalink
feat(geom): add asPolygon() support for complexpoly & path
Browse files Browse the repository at this point in the history
BREAKING CHANGE: update asPolygon() to return array of polygons (rather than single only)

- add support for complexpoly & path (incl. sub-shapes, holes)
- refactor internal call sites
  • Loading branch information
postspectacular committed May 4, 2024
1 parent f758425 commit e3c9f20
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 68 deletions.
5 changes: 4 additions & 1 deletion packages/geom/src/area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ export const area: MultiFn1O<IShape, boolean, number> = defmulti(
group: ({ children }: Group) =>
children.reduce((sum, $) => sum + area($, false), 0),

path: ($: Path) => ($.closed ? area(asPolygon($)) : 0),
path: ($: Path) => {
if (!$.closed) return 0;
return asPolygon($).reduce((acc, p) => acc + area(p, true), 0);
},

plane: () => Infinity,

Expand Down
19 changes: 13 additions & 6 deletions packages/geom/src/as-cubic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ import { __dispatch } from "./internal/dispatch.js";
* @param shape
* @param opts
*/
export const asCubic: MultiFn1O<IShape, Partial<CubicOpts>, Cubic[]> = defmulti(
export const asCubic: MultiFn1O<IShape, Partial<CubicOpts>, Cubic[]> = defmulti<
any,
Partial<CubicOpts> | undefined,
Cubic[]
>(
__dispatch,
{
ellipse: "circle",
Expand All @@ -75,9 +79,13 @@ export const asCubic: MultiFn1O<IShape, Partial<CubicOpts>, Cubic[]> = defmulti(

circle: ($: Circle) => asCubic(arc($.pos, $.r, 0, 0, TAU, true, true)),

// complexpoly: ($: ComplexPolygon, opts = {}) => [
// ...mapcat((x) => asCubic(x, opts), [$.boundary, ...$.children]),
// ],

cubic: ($: Cubic) => [$],

group: ($: Group, opts?: Partial<CubicOpts>) => [
group: ($: Group, opts) => [
...mapcat((x) => asCubic(x, opts), $.children),
],

Expand All @@ -89,15 +97,15 @@ export const asCubic: MultiFn1O<IShape, Partial<CubicOpts>, Cubic[]> = defmulti(
...mapcat((s) => (s.geo ? asCubic(s.geo) : null), $.segments),
],

poly: ($: Polygon, opts: Partial<CubicOpts> = {}) =>
poly: ($: Polygon, opts = {}) =>
__polyCubic(
$,
opts,
closedCubicFromBreakPoints,
closedCubicFromControlPoints
),

polyline: ($: Polyline, opts: Partial<CubicOpts> = {}) =>
polyline: ($: Polyline, opts = {}) =>
__polyCubic(
$,
opts,
Expand All @@ -109,8 +117,7 @@ export const asCubic: MultiFn1O<IShape, Partial<CubicOpts>, Cubic[]> = defmulti(
cubicFromQuadratic(points[0], points[1], points[2], { ...attribs }),
],

rect: ($: Rect, opts?: Partial<CubicOpts>) =>
asCubic(asPolygon($), opts),
rect: ($: Rect, opts) => asCubic(asPolygon($)[0], opts),
}
);

Expand Down
33 changes: 26 additions & 7 deletions packages/geom/src/as-polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@ import type { Maybe } from "@thi.ng/api";
import type { MultiFn1O } from "@thi.ng/defmulti";
import { defmulti } from "@thi.ng/defmulti/defmulti";
import type { IShape, SamplingOpts } from "@thi.ng/geom-api";
import type { ComplexPolygon } from "./api/complex-polygon.js";
import { Path } from "./api/path.js";
import { Polygon } from "./api/polygon.js";
import { __copyAttribsNoSamples as __attribs } from "./internal/copy.js";
import { __dispatch } from "./internal/dispatch.js";
import { vertices } from "./vertices.js";

/**
* Converts given shape into a {@link Polygon}, optionally using provided
* Converts given shape into an array of {@link Polygon}s, optionally using
* provided
* [`SamplingOpts`](https://docs.thi.ng/umbrella/geom-api/interfaces/SamplingOpts.html)
* or number of target vertices.
*
* @remarks
* If the shape has a `__samples` attribute, it will be removed in the result to
* avoid recursive application.
* If the input shape has a `__samples` attribute, it will be removed in the
* results polys to avoid recursive application.
*
* Currently implemented for:
*
* - {@link Circle}
* - {@link ComplexPolygon}
* - {@link Ellipse}
* - {@link Line}
* - {@link Line} (will be closed)
* - {@link Path}
* - {@link Polygon}
* - {@link Polyline} (will be closed)
Expand All @@ -34,8 +38,8 @@ import { vertices } from "./vertices.js";
export const asPolygon: MultiFn1O<
IShape,
number | Partial<SamplingOpts>,
Polygon
> = defmulti<IShape, Maybe<number | Partial<SamplingOpts>>, Polygon>(
Polygon[]
> = defmulti<any, Maybe<number | Partial<SamplingOpts>>, Polygon[]>(
__dispatch,
{
circle: "points",
Expand All @@ -49,6 +53,21 @@ export const asPolygon: MultiFn1O<
tri: "points",
},
{
points: ($, opts) => new Polygon(vertices($, opts), __attribs($)),
complexpoly: ($: ComplexPolygon, opts) =>
[$.boundary, ...$.children].map(
(x) => new Polygon(vertices(x, opts), __attribs($))
),

path: ($: Path, opts) => {
const tmp = new Path();
return [$.segments, ...$.subPaths].map((segments) => {
tmp.segments = segments;
return new Polygon(vertices(tmp, opts), __attribs($));
});
},

points: ($: IShape, opts) => [
new Polygon(vertices($, opts), __attribs($)),
],
}
);
21 changes: 7 additions & 14 deletions packages/geom/src/as-polyline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { peek } from "@thi.ng/arrays/peek";
import type { MultiFn1O } from "@thi.ng/defmulti";
import { defmulti } from "@thi.ng/defmulti/defmulti";
import type { IShape, SamplingOpts } from "@thi.ng/geom-api";
import { map } from "@thi.ng/transducers/map";
import { mapcat } from "@thi.ng/transducers/mapcat";
import { set } from "@thi.ng/vectors/set";
import type { ComplexPolygon } from "./api/complex-polygon.js";
Expand All @@ -15,7 +14,7 @@ import { __dispatch } from "./internal/dispatch.js";
import { vertices } from "./vertices.js";

/**
* Converts given shape into an array of {@link Polyline}, optionally using
* Converts given shape into an array of {@link Polyline}s, optionally using
* provided
* [`SamplingOpts`](https://docs.thi.ng/umbrella/geom-api/interfaces/SamplingOpts.html)
* or number of target vertices.
Expand Down Expand Up @@ -75,18 +74,12 @@ export const asPolyline: MultiFn1O<

path: ($: Path, opts) => {
const tmp = new Path();
return [
...map(
(segments) => {
tmp.segments = segments;
const pts = vertices(tmp, opts);
peek(segments).type === "z" &&
pts.push(set([], pts[0]));
return new Polyline(pts, __attribs($));
},
[$.segments, ...$.subPaths]
),
];
return [$.segments, ...$.subPaths].map((segments) => {
tmp.segments = segments;
const pts = vertices(tmp, opts);
peek(segments).type === "z" && pts.push(set([], pts[0]));
return new Polyline(pts, __attribs($));
});
},

poly: ($, opts) => {
Expand Down
8 changes: 5 additions & 3 deletions packages/geom/src/edges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,12 @@ export const edges: MultiFn1O<
];
},

arc: ($: Arc, opts) => __edges(asPolyline($, opts)[0].points, false),
arc: ($: Arc, opts) => __edges(asPolyline($, opts)[0].points),

bpatch: ($: BPatch) => $.edges(),

circle: ($: Circle, opts) => __edges(asPolygon($, opts).points, true),
circle: ($: Circle, opts) =>
__edges(asPolygon($, opts)[0].points, true),

complexpoly: ($: ComplexPolygon) =>
mapcat(
Expand All @@ -109,7 +110,8 @@ export const edges: MultiFn1O<

group: ($: Group, opts) => mapcat((c) => edges(c, opts), $.children),

path: ($: Path, opts) => __edges(asPolygon($, opts).points, $.closed),
path: ($: Path, opts) =>
mapcat((poly) => __edges(poly.points), asPolyline($, opts)),

poly: ($: Polygon) => __edges($.points, true),

Expand Down
2 changes: 1 addition & 1 deletion packages/geom/src/resample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const resample: MultiFn2<
rect: "circle",
},
{
circle: ($: IShape, opts) => asPolygon($, opts),
circle: ($: IShape, opts) => asPolygon($, opts)[0],

complexpoly: ($: ComplexPolygon, opts) =>
new ComplexPolygon(
Expand Down
2 changes: 1 addition & 1 deletion packages/geom/src/rotate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const rotate: MultiFn2<IShape, number, IShape> = defmulti<
);
},

rect: ($: Rect, theta) => rotate(asPolygon($), theta),
rect: ($: Rect, theta) => rotate(asPolygon($)[0], theta),

text: ($: Text, theta) =>
new Text($rotate([], $.pos, theta), $.body, __copyAttribs($)),
Expand Down
71 changes: 37 additions & 34 deletions packages/geom/src/subdiv-curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,45 +44,48 @@ import { __dispatch } from "./internal/dispatch.js";
* @param kernel
* @param iter
*/
export const subdivCurve: MultiFn2O<IShape, SubdivKernel, number, IShape> =
defmulti<any, SubdivKernel, Maybe<number>, IShape>(
__dispatch,
{
ellipse: "circle",
line: "polyline",
quad: "poly",
rect: "circle",
tri: "poly",
},
{
arc: ($, kernel, iter = 1) =>
subdivCurve(asPolyline($)[0], kernel, iter),
export const subdivCurve: MultiFn2O<
IShape,
SubdivKernel,
number,
ComplexPolygon | Polygon | Polyline
> = defmulti<
any,
SubdivKernel,
Maybe<number>,
ComplexPolygon | Polygon | Polyline
>(
__dispatch,
{
ellipse: "circle",
line: "polyline",
quad: "poly",
rect: "circle",
tri: "poly",
},
{
arc: ($, kernel, iter = 1) =>
subdivCurve(asPolyline($)[0], kernel, iter),

circle: ($, kernel, iter = 1) =>
subdivCurve(asPolygon($), kernel, iter),
circle: ($, kernel, iter = 1) =>
subdivCurve(asPolygon($)[0], kernel, iter),

complexpoly: ($: ComplexPolygon, kernel, iter) =>
new ComplexPolygon(
<Polygon>subdivCurve($.boundary, kernel, iter),
$.children.map(
(child) => <Polygon>subdivCurve(child, kernel, iter)
),
__copyAttribs($)
complexpoly: ($: ComplexPolygon, kernel, iter) =>
new ComplexPolygon(
<Polygon>subdivCurve($.boundary, kernel, iter),
$.children.map(
(child) => <Polygon>subdivCurve(child, kernel, iter)
),
__copyAttribs($)
),

poly: ($: Polygon, kernel, iter = 1) =>
new Polygon(
subdivide($.points, kernel, iter),
__copyAttribs($)
),
poly: ($: Polygon, kernel, iter = 1) =>
new Polygon(subdivide($.points, kernel, iter), __copyAttribs($)),

polyline: ($: Polyline, kernel, iter = 1) =>
new Polyline(
subdivide($.points, kernel, iter),
__copyAttribs($)
),
}
);
polyline: ($: Polyline, kernel, iter = 1) =>
new Polyline(subdivide($.points, kernel, iter), __copyAttribs($)),
}
);

/**
* Re-export of thi.ng/geom-subdiv-curve
Expand Down
2 changes: 1 addition & 1 deletion packages/geom/src/transform-vertices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export const transformVertices: MultiFn2<

quadratic: tx(Quadratic),

rect: ($: Rect, fn) => transformVertices(asPolygon($), fn),
rect: ($: Rect, fn) => transformVertices(asPolygon($)[0], fn),

tri: tx(Triangle),
}
Expand Down

0 comments on commit e3c9f20

Please sign in to comment.