Skip to content

Commit 906a326

Browse files
feat(geom): add splitArclength()
1 parent 1359645 commit 906a326

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

packages/geom/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@
334334
"./sphere": {
335335
"default": "./sphere.js"
336336
},
337+
"./split-arclength": {
338+
"default": "./split-arclength.js"
339+
},
337340
"./split-at": {
338341
"default": "./split-at.js"
339342
},

packages/geom/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export * from "./rotate.js";
7171
export * from "./scale.js";
7272
export * from "./scatter.js";
7373
export * from "./simplify.js";
74+
export * from "./split-arclength.js";
7475
export * from "./split-at.js";
7576
export * from "./split-near.js";
7677
export * from "./subdiv-curve.js";

packages/geom/src/split-arclength.ts

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { MultiFn2 } from "@thi.ng/defmulti";
2+
import { DEFAULT, defmulti } from "@thi.ng/defmulti/defmulti";
3+
import type { IHiccupShape, IShape } from "@thi.ng/geom-api";
4+
import { Sampler } from "@thi.ng/geom-resample/sampler";
5+
import { mapcat } from "@thi.ng/transducers/mapcat";
6+
import type { Vec } from "@thi.ng/vectors";
7+
import { Group } from "./api/group.js";
8+
import { Polyline } from "./api/polyline.js";
9+
import { asPolyline } from "./as-polyline.js";
10+
import { __copyAttribs } from "./internal/copy.js";
11+
import { __dispatch } from "./internal/dispatch.js";
12+
import { __pointArraysAsShapes } from "./internal/points-as-shape.js";
13+
14+
/**
15+
* Splits given shape into {@link Polyline} segments of given (max) arc length.
16+
* Returns array of new shapes/polylines.
17+
*
18+
* @remarks
19+
* Currently only implemented for:
20+
*
21+
* - {@link Group}
22+
* - {@link Polyline}
23+
*
24+
* Other shape types will be attempted to be auto-converted via
25+
* {@link asPolyline} first.
26+
*
27+
* @param shape
28+
* @param dist
29+
*/
30+
export const splitArclength: MultiFn2<IShape, number, IShape[]> = defmulti<
31+
any,
32+
number,
33+
IShape[]
34+
>(
35+
__dispatch,
36+
{},
37+
{
38+
[DEFAULT]: ($: IShape, d: number) => splitArclength(asPolyline($), d),
39+
40+
group: ($, d) => [
41+
new Group(__copyAttribs($.attribs), [
42+
...mapcat(
43+
(c: IShape) => <IHiccupShape[]>splitArclength(c, d),
44+
$.children
45+
),
46+
]),
47+
],
48+
49+
polyline: ($: Polyline, d) => {
50+
const chunks: Vec[][] = [];
51+
let pts = $.points;
52+
while (true) {
53+
const sampler = new Sampler(pts);
54+
const total = sampler.totalLength();
55+
if (total > d) {
56+
const parts = sampler.splitAt(d / total);
57+
if (!parts) break;
58+
chunks.push(parts[0]);
59+
pts = parts[1];
60+
} else {
61+
chunks.push(pts);
62+
break;
63+
}
64+
}
65+
return __pointArraysAsShapes(Polyline, chunks, $.attribs)!;
66+
},
67+
}
68+
);

0 commit comments

Comments
 (0)