Skip to content

Commit

Permalink
feat(geom): add/update resample()/simplify()/subdivCurve() impls
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed May 17, 2024
1 parent 9b4df2e commit 1682577
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 71 deletions.
95 changes: 68 additions & 27 deletions packages/geom/src/resample.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import type { MultiFn2 } from "@thi.ng/defmulti";
import { defmulti } from "@thi.ng/defmulti/defmulti";
import type { IShape, PCLike, SamplingOpts } from "@thi.ng/geom-api";
import type { IShape, IShape2, PCLike, SamplingOpts } from "@thi.ng/geom-api";
import { resample as _resample } from "@thi.ng/geom-resample/resample";
import { ComplexPolygon } from "./api/complex-polygon.js";
import type { Line } from "./api/line.js";
import { Polygon } from "./api/polygon.js";
import { Polyline } from "./api/polyline.js";
import { Polyline3 } from "./api/polyline3.js";
import { asPolygon } from "./as-polygon.js";
import { asPolyline } from "./as-polyline.js";
import { __copyAttribsNoSamples as __attribs } from "./internal/copy.js";
import { __dispatch } from "./internal/dispatch.js";
import { Polygon3 } from "./api/polygon3.js";

export type ResampleFn = {
(
shape: ComplexPolygon,
opts: number | Partial<SamplingOpts>
): ComplexPolygon;
(shape: Line, opts: number | Partial<SamplingOpts>): Polyline;
(shape: Polyline, opts: number | Partial<SamplingOpts>): Polyline;
(shape: IShape2, opts: number | Partial<SamplingOpts>): Polygon;
} & MultiFn2<IShape, number | Partial<SamplingOpts>, IShape>;

/**
* Resamples given 2D shape with given options and returns result as polygon (if
Expand All @@ -32,33 +46,60 @@ import { __dispatch } from "./internal/dispatch.js";
* @param shape
* @param opts
*/
export const resample: MultiFn2<
IShape,
number | Partial<SamplingOpts>,
IShape
> = defmulti<any, number | Partial<SamplingOpts>, IShape>(
__dispatch,
{
ellipse: "circle",
line: "polyline",
quad: "poly",
tri: "poly",
rect: "circle",
},
{
circle: ($: IShape, opts) => asPolygon($, opts)[0],
export const resample = <ResampleFn>(
defmulti<any, number | Partial<SamplingOpts>, IShape>(
__dispatch,
{
arc: "$aspolyline",
circle: "$aspoly",
cubic: "$aspolyline",
cubic3: "$aspolyline",
ellipse: "$aspoly",
line: "polyline",
line3: "polyline3",
quad: "poly",
quad3: "poly3",
quadratic: "$aspolyline",
quadratic3: "$aspolyline",
rect: "circle",
tri: "poly",
tri3: "poly3",
},
{
$aspoly: ($: IShape, opts) => asPolygon($, opts)[0],

$aspolyline: ($: IShape, opts) => asPolyline($, opts)[0],

complexpoly: ($: ComplexPolygon, opts) =>
new ComplexPolygon(
resample($.boundary, opts),
$.children.map((child) => resample(child, opts)),
__attribs($)
),

poly: ($: PCLike, opts) =>
new Polygon(
_resample($.points, opts, true, true),
__attribs($)
),

complexpoly: ($: ComplexPolygon, opts) =>
new ComplexPolygon(
<Polygon>resample($.boundary, opts),
$.children.map((child) => <Polygon>resample(child, opts)),
__attribs($)
),
poly3: ($: PCLike, opts) =>
new Polygon3(
_resample($.points, opts, true, true),
__attribs($)
),

poly: ($: PCLike, opts) =>
new Polygon(_resample($.points, opts, true, true), __attribs($)),
polyline: ($: PCLike, opts) =>
new Polyline(
_resample($.points, opts, false, true),
__attribs($)
),

polyline: ($: PCLike, opts) =>
new Polyline(_resample($.points, opts, false, true), __attribs($)),
}
polyline3: ($: PCLike, opts) =>
new Polyline3(
_resample($.points, opts, false, true),
__attribs($)
),
}
)
);
16 changes: 8 additions & 8 deletions packages/geom/src/simplify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Maybe } from "@thi.ng/api";
import { peek } from "@thi.ng/arrays/peek";
import type { MultiFn1O } from "@thi.ng/defmulti";
import { defmulti } from "@thi.ng/defmulti/defmulti";
import type { IShape, PathSegment } from "@thi.ng/geom-api";
import type { IShape, IShape2, PathSegment2 } from "@thi.ng/geom-api";
import { simplify as _simplify } from "@thi.ng/geom-resample/simplify";
import type { Vec } from "@thi.ng/vectors";
import { ComplexPolygon } from "./api/complex-polygon.js";
Expand All @@ -13,6 +13,10 @@ import { __copyAttribs } from "./internal/copy.js";
import { __dispatch } from "./internal/dispatch.js";
import { vertices } from "./vertices.js";

export type SimplifyFn = {
<T extends IShape2>(shape: IShape2, eps?: number): T;
} & MultiFn1O<IShape, number, IShape>;

/**
* Simplifies given 2D shape boundary using Douglas-Peucker algorithm
* (implemented by
Expand All @@ -34,11 +38,7 @@ import { vertices } from "./vertices.js";
* @param shape
* @param threshold
*/
export const simplify: MultiFn1O<IShape, number, IShape> = defmulti<
any,
Maybe<number>,
IShape
>(
export const simplify = <SimplifyFn>defmulti<any, Maybe<number>, IShape>(
__dispatch,
{},
{
Expand All @@ -50,8 +50,8 @@ export const simplify: MultiFn1O<IShape, number, IShape> = defmulti<
),

path: ($: Path, eps = 1e-6) => {
const $simplifySegments = (segments: PathSegment[]) => {
const res: PathSegment[] = [];
const $simplifySegments = (segments: PathSegment2[]) => {
const res: PathSegment2[] = [];
const n = segments.length;
let points!: Vec[] | null;
let lastP!: Vec;
Expand Down
80 changes: 44 additions & 36 deletions packages/geom/src/subdiv-curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import { asPolyline } from "./as-polyline.js";
import { __copyAttribs } from "./internal/copy.js";
import { __dispatch } from "./internal/dispatch.js";

export type SubdivCurveFn = {
(
shape: ComplexPolygon,
kernel: SubdivKernel,
iter?: number
): ComplexPolygon;
(shape: Polygon, kernel: SubdivKernel, iter?: number): Polygon;
(shape: Polyline, kernel: SubdivKernel, iter?: number): Polyline;
} & MultiFn2O<IShape, SubdivKernel, number, IShape>;

/**
* Recursively applies
* [`SubdivKernel`](https://docs.thi.ng/umbrella/geom-api/interfaces/SubdivKernel.html)
Expand Down Expand Up @@ -44,47 +54,45 @@ import { __dispatch } from "./internal/dispatch.js";
* @param kernel
* @param 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),
export const subdivCurve = <SubdivCurveFn>(
defmulti<any, SubdivKernel, Maybe<number>, IShape>(
__dispatch,
{
arc: "$aspolyline",
circle: "$aspoly",
ellipse: "$aspoly",
line: "polyline",
quad: "poly",
rect: "$aspoly",
tri: "poly",
},
{
$aspolyline: ($, kernel, iter = 1) =>
subdivCurve(asPolyline($)[0], kernel, iter),

circle: ($, kernel, iter = 1) =>
subdivCurve(asPolygon($)[0], kernel, iter),
$aspoly: ($, 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)
complexpoly: ($: ComplexPolygon, kernel, iter) =>
new ComplexPolygon(
subdivCurve($.boundary, kernel, iter),
$.children.map((child) => subdivCurve(child, kernel, iter)),
__copyAttribs($)
),
__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($)
),
}
)
);

/**
Expand Down

0 comments on commit 1682577

Please sign in to comment.