@cgtk/gp 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/gp.wasm CHANGED
Binary file
package/index.d.ts CHANGED
@@ -1,77 +1,146 @@
1
- import type { Fn, FnV, Resource, TypedArray } from "@cgtk/std/types";
2
- import { type View, type Struct } from "@cgtk/std/struct";
3
- import { type Constructor } from "@cgtk/std/typedarray";
4
- import type { IndexedMesh } from "@cgtk/geometry/types";
1
+ import type { Fn, FnV, NumberArray } from "@cgtk/std/types";
2
+ import { type Struct } from "@cgtk/std/struct";
3
+ import * as TA from "@cgtk/std/typedarray";
4
+ import type { Vec2 } from "@cgtk/linalg/types";
5
+ import { type Point } from "./point";
5
6
  export declare const wasmInit: <T>(source: Response | PromiseLike<Response>, imports?: WebAssembly.Imports) => Promise<T>;
6
7
  interface Mod {
7
8
  memory: WebAssembly.Memory;
8
- malloc(size: number): number;
9
- free(ptr: number, size: number): number;
10
- }
11
- interface Alloc<T> {
12
- ptr: number;
13
- value: T;
14
- }
15
- export interface GP extends Mod {
16
- vertex_position_geometry: FnV<[number, number], number>;
17
- free_vertex_position_geometry: Fn<number, void>;
18
- n_faces: Fn<number, number>;
19
- n_halfedges: Fn<number, number>;
20
- h2f: FnV<[number, number], number>;
21
- f2h: FnV<[number, number], number>;
22
- h_next: FnV<[number, number], number>;
23
- h_twin: FnV<[number, number], number>;
24
- double_area: FnV<[number, number], number>;
25
- double_areas: FnV<[number, number], void>;
26
- face_normals: FnV<[number, number], void>;
27
- internal_angles: FnV<[number, number], void>;
28
- vertex_normals_area_weighted: FnV<[number, number], void>;
29
- vertex_normals_angle_weighted: FnV<[number, number], void>;
30
- angle_defects: FnV<[number, number], void>;
9
+ __heap_base: WebAssembly.Global;
10
+ malloc(size: number, align: number): number;
11
+ free(ptr: number, size: number, align: number): number;
31
12
  }
32
13
  export declare const allocators: (mod: Mod) => {
33
- struct: <T extends Struct<any>>(s: T) => Resource<Alloc<View<T>>>;
34
- array: <T extends TypedArray>(ctor: Constructor<T>, length: number) => Resource<Alloc<T>>;
35
- data: <T extends TypedArray>(vals: T) => Resource<Alloc<T>>;
36
- slice: <T extends TypedArray>(a: Alloc<T>) => Resource<Alloc<{
14
+ struct: <T extends Struct<any>>(s: T) => import("@cgtk/std/types").Resource<{
37
15
  ptr: number;
38
- len: number;
39
- }>>;
40
- dataSlice: <T extends TypedArray>(data: T) => Resource<Alloc<{
16
+ value: import("@cgtk/std/struct").View<T>;
17
+ }>;
18
+ array: <T extends NumberArray>(ctor: TA.Constructor<T>, length: number) => import("@cgtk/std/types").Resource<{
41
19
  ptr: number;
42
- len: number;
43
- }>>;
20
+ value: T;
21
+ slice: bigint;
22
+ }>;
23
+ data: <T extends NumberArray>(vals: T) => import("@cgtk/std/types").Resource<{
24
+ ptr: number;
25
+ value: T;
26
+ slice: bigint;
27
+ }>;
44
28
  };
45
- export declare const init: (url?: any, imports?: WebAssembly.Imports) => Promise<{
29
+ export interface GP extends Mod {
30
+ surface_new: Fn<bigint, number>;
31
+ surface_free: Fn<number, void>;
32
+ surface_n_faces: Fn<number, number>;
33
+ surface_n_halfedges: Fn<number, number>;
34
+ surface_h2f: FnV<[number, number], number>;
35
+ surface_f2h: FnV<[number, number], number>;
36
+ surface_h_next: FnV<[number, number], number>;
37
+ surface_h_twin: FnV<[number, number], number>;
38
+ surface_double_area: FnV<[number, number], number>;
39
+ surface_double_areas: FnV<[number, bigint], void>;
40
+ surface_face_normal: FnV<[number, number, bigint], void>;
41
+ surface_face_normals: FnV<[number, bigint], void>;
42
+ surface_internal_angles: FnV<[number, bigint], void>;
43
+ surface_vertex_normals_area_weighted: FnV<[number, bigint], void>;
44
+ surface_vertex_normals_angle_weighted: FnV<[number, bigint], void>;
45
+ surface_angle_defects: FnV<[number, bigint], void>;
46
+ manifold_new: Fn<bigint, number>;
47
+ manifold_free: Fn<number, void>;
48
+ manifold_n_faces: Fn<number, number>;
49
+ manifold_n_halfedges: Fn<number, number>;
50
+ manifold_h2f: FnV<[number, number], number>;
51
+ manifold_f2h: FnV<[number, number], number>;
52
+ manifold_h_next: FnV<[number, number], number>;
53
+ manifold_h_twin: FnV<[number, number], number>;
54
+ manifold_face_area_f: FnV<[number, number], number>;
55
+ manifold_face_area_d: FnV<[number, number], number>;
56
+ signpost_f_new: Fn<number, number>;
57
+ signpost_f_free: Fn<number, void>;
58
+ signpost_f_flip_to_delaunay: Fn<number, number>;
59
+ signpost_f_trace_along_input: FnV<[number, number, number, number], bigint>;
60
+ free_points_f: Fn<bigint, void>;
61
+ signpost_d_new: Fn<number, number>;
62
+ signpost_d_free: Fn<number, void>;
63
+ signpost_d_flip_to_delaunay: Fn<number, number>;
64
+ signpost_d_trace_along_input: FnV<[number, number, number, number], bigint>;
65
+ free_points_d: Fn<bigint, void>;
66
+ geodesic_tracer_f_new: Fn<number, number>;
67
+ geodesic_tracer_f_free: Fn<number, void>;
68
+ geodesic_tracer_f_trace_start: FnV<[number, number, number, bigint], number>;
69
+ geodesic_tracer_f_trace_next: FnV<[number, number, number], number>;
70
+ geodesic_tracer_f_trace_result_free: Fn<number, void>;
71
+ geodesic_tracer_f_trace_state_free: Fn<number, void>;
72
+ geodesic_tracer_d_new: Fn<number, number>;
73
+ geodesic_tracer_d_free: Fn<number, void>;
74
+ geodesic_tracer_d_trace_start: FnV<[number, number, number, bigint], number>;
75
+ geodesic_tracer_d_trace_next: FnV<[number, number, number], number>;
76
+ geodesic_tracer_d_trace_result_free: Fn<number, void>;
77
+ geodesic_tracer_d_trace_state_free: Fn<number, void>;
78
+ }
79
+ type Float<T extends ArrayBufferLike = ArrayBufferLike> = Float32Array<T> | Float64Array<T>;
80
+ export declare const init: (url?: string | URL | Request, imports?: WebAssembly.Imports) => Promise<{
46
81
  alloc: {
47
- struct: <T extends Struct<any>>(s: T) => Resource<Alloc<View<T>>>;
48
- array: <T extends TypedArray>(ctor: Constructor<T>, length: number) => Resource<Alloc<T>>;
49
- data: <T extends TypedArray>(vals: T) => Resource<Alloc<T>>;
50
- slice: <T extends TypedArray>(a: Alloc<T>) => Resource<Alloc<{
82
+ struct: <T extends Struct<any>>(s: T) => import("@cgtk/std/types").Resource<{
51
83
  ptr: number;
52
- len: number;
53
- }>>;
54
- dataSlice: <T extends TypedArray>(data: T) => Resource<Alloc<{
84
+ value: import("@cgtk/std/struct").View<T>;
85
+ }>;
86
+ array: <T extends NumberArray>(ctor: TA.Constructor<T>, length: number) => import("@cgtk/std/types").Resource<{
55
87
  ptr: number;
56
- len: number;
57
- }>>;
88
+ value: T;
89
+ slice: bigint;
90
+ }>;
91
+ data: <T extends NumberArray>(vals: T) => import("@cgtk/std/types").Resource<{
92
+ ptr: number;
93
+ value: T;
94
+ slice: bigint;
95
+ }>;
58
96
  };
59
- vertexPositionGeometry: (mesh: IndexedMesh<{
60
- position: Float32Array;
61
- }, Uint32Array>) => Resource<{
97
+ surface: (indices: Uint32Array) => import("@cgtk/std/types").Resource<{
98
+ nFaces: () => number;
99
+ nHalfedges: () => number;
100
+ h2f: (i: number) => number;
101
+ hNext: (i: number) => number;
102
+ hTwin: (i: number) => number;
103
+ f2h: (i: number) => number;
104
+ geometry: (positions: Float32Array) => import("@cgtk/std/types").Resource<{
105
+ doubleArea: (i: number) => number;
106
+ doubleAreas: <T extends Float = Float32Array<ArrayBufferLike>>(res?: T) => T;
107
+ faceNormal: <T extends Float = Float32Array<ArrayBufferLike>>(f: number, res?: T) => T;
108
+ faceNormals: <T extends Float = Float32Array<ArrayBufferLike>>(res?: T) => T;
109
+ internalAngles: <T extends Float = Float32Array<ArrayBufferLike>>(res?: T) => T;
110
+ angleDefects: <T extends Float = Float32Array<ArrayBufferLike>>(res?: T) => T;
111
+ vertexNormalsAreaWeighted: <T extends Float = Float32Array<ArrayBufferLike>>(res?: T) => T;
112
+ vertexNormalsAngleWeighted: <T extends Float = Float32Array<ArrayBufferLike>>(res?: T) => T;
113
+ }>;
114
+ }>;
115
+ manifold: (indices: Uint32Array) => import("@cgtk/std/types").Resource<{
62
116
  nFaces: () => number;
63
117
  nHalfedges: () => number;
64
118
  h2f: (i: number) => number;
65
119
  hNext: (i: number) => number;
66
120
  hTwin: (i: number) => number;
67
121
  f2h: (i: number) => number;
68
- doubleArea: (i: number) => number;
69
- doubleAreas: <T extends TypedArray>(res: T) => T;
70
- faceNormals: <T extends TypedArray>(res: T) => T;
71
- internalAngles: <T extends TypedArray>(res: T) => T;
72
- vertexNormalsAreaWeighted: <T extends TypedArray>(res: T) => T;
73
- vertexNormalsAngleWeighted: <T extends TypedArray>(res: T) => T;
74
- angleDefects: <T extends TypedArray>(res: T) => T;
122
+ geometryF: (positions: Float32Array) => import("@cgtk/std/types").Resource<{
123
+ faceArea: (i: number) => number;
124
+ tracer: () => import("@cgtk/std/types").Resource<{
125
+ ptr: number;
126
+ trace: (p: Point<Float32Array>, tVec: Vec2<Float32Array>) => Generator<Point<Float32Array<ArrayBufferLike>>, void, unknown>;
127
+ }>;
128
+ signpost: () => import("@cgtk/std/types").Resource<{
129
+ flipToDelaunay: () => number;
130
+ traceAlongInput: (tracer: number, i: number) => Point<Float32Array<ArrayBufferLike>>[];
131
+ }>;
132
+ }>;
133
+ geometryD: (positions: Float64Array) => import("@cgtk/std/types").Resource<{
134
+ faceArea: (i: number) => number;
135
+ tracer: () => import("@cgtk/std/types").Resource<{
136
+ ptr: number;
137
+ trace: (p: Point<Float64Array>, tVec: Vec2<Float64Array>) => Generator<Point<Float64Array<ArrayBufferLike>>, void, unknown>;
138
+ }>;
139
+ signpost: () => import("@cgtk/std/types").Resource<{
140
+ flipToDelaunay: () => number;
141
+ traceAlongInput: (tracer: number, i: number) => Point<Float64Array<ArrayBufferLike>>[];
142
+ }>;
143
+ }>;
75
144
  }>;
76
145
  }>;
77
146
  export {};
package/index.js CHANGED
@@ -1,75 +1,218 @@
1
- import { bind } from "@cgtk/std/fn";
2
- import { resource, map, flatMap, combine } from "@cgtk/std/resource";
3
- import { struct, view, u32 } from "@cgtk/std/struct";
4
- import { ctor } from "@cgtk/std/typedarray";
1
+ import { resource, map, combine } from "@cgtk/std/resource";
2
+ import { view, array } from "@cgtk/std/struct";
3
+ import * as TA from "@cgtk/std/typedarray";
4
+ import * as S from "./struct";
5
+ import { from as fromPoint, PointType } from "./point";
5
6
  import wasmURL from './gp.wasm?url';
6
7
  export const wasmInit = async (source, imports) => (await WebAssembly.instantiateStreaming(source, imports)).instance.exports;
7
- ;
8
+ const packSlice = (ptr, len) => ((BigInt(len) & 0xffffffffn) << 32n) | (BigInt(ptr) & 0xffffffffn);
9
+ const unpackSlice = (val) => ({ ptr: Number(val & 0xffffffffn), len: Number(val >> 32n) });
8
10
  const allocStruct = (mod, s) => {
9
- const ptr = mod.malloc(s.size);
11
+ const ptr = mod.malloc(s.size, s.align);
10
12
  const value = view(s, mod.memory.buffer, ptr);
11
- return resource({ ptr, value }, () => mod.free(ptr, s.size));
13
+ return resource({ ptr, value }, () => mod.free(ptr, s.size, s.align));
12
14
  };
13
15
  const allocArray = (mod, ctor, length) => {
14
- const ptr = mod.malloc(ctor.BYTES_PER_ELEMENT * length);
16
+ const ptr = mod.malloc(ctor.BYTES_PER_ELEMENT * length, ctor.BYTES_PER_ELEMENT);
15
17
  const value = new ctor(mod.memory.buffer, ptr, length);
16
- return resource({ ptr, value }, () => mod.free(ptr, value.byteLength));
18
+ const slice = packSlice(ptr, value.length);
19
+ return resource({ ptr, value, slice }, () => mod.free(ptr, value.byteLength, ctor.BYTES_PER_ELEMENT));
17
20
  };
18
- const allocdata = (mod, data) => map(allocArray(mod, ctor(data), data.length), p => {
21
+ const allocdata = (mod, data) => map(allocArray(mod, TA.ctor(data), data.length), p => {
19
22
  p.value.set(data);
20
23
  return p;
21
24
  });
22
- const Slice = struct([["ptr", u32()], ["len", u32()]]);
23
- const allocSlice = (mod, a) => map(allocStruct(mod, Slice), x => {
24
- x.value.ptr = a.ptr;
25
- x.value.len = a.value.length;
26
- return x;
27
- });
28
- const allocDataSlice = (mod, data) => flatMap(allocdata(mod, data), bind((allocSlice), mod));
29
25
  export const allocators = (mod) => ({
30
26
  struct: (s) => allocStruct(mod, s),
31
27
  array: (ctor, length) => allocArray(mod, ctor, length),
32
28
  data: (vals) => allocdata(mod, vals),
33
- slice: (a) => allocSlice(mod, a),
34
- dataSlice: (data) => allocDataSlice(mod, data),
35
29
  });
36
30
  export const init = async (url = wasmURL, imports = {
37
- env: {
38
- memory: new WebAssembly.Memory({ initial: 20, maximum: 100 })
39
- },
40
31
  console: { log: console.log },
41
32
  }) => {
42
- const mod = await wasmInit(fetch(url), imports);
33
+ const mod = await wasmInit(fetch(url), {
34
+ ...imports,
35
+ env: {
36
+ js_panic_logger(ptr, len, line) {
37
+ const data = new Uint8Array(mod.memory.buffer, ptr, len);
38
+ const fileName = new TextDecoder().decode(data);
39
+ console.error(`WASM PANIC: ${fileName}:${line}`);
40
+ },
41
+ js_oom_trap(size, align) {
42
+ console.error(`WASM Out of Memory! Failed to allocate ${size} bytes with ${align} alignment.`);
43
+ }
44
+ }
45
+ });
43
46
  const alloc = allocators(mod);
47
+ const withSlice = (res, f) => {
48
+ alloc.array(TA.ctor(res), res.length)(data => {
49
+ f(data.slice);
50
+ res.set(data.value);
51
+ })();
52
+ return res;
53
+ };
44
54
  return {
45
55
  alloc,
46
- vertexPositionGeometry: (mesh) => flatMap(combine({
47
- pFace: alloc.dataSlice(mesh.indices),
48
- pPos: alloc.dataSlice(mesh.attribs.position)
49
- }), ({ pFace, pPos }) => {
50
- const ptr = mod.vertex_position_geometry(pFace.ptr, pPos.ptr);
51
- const withResult = (res, f) => {
52
- alloc.array(ctor(res), res.length)(data => alloc.slice(data)(s => {
53
- f(s);
54
- res.set(data.value);
55
- }))();
56
- return res;
57
- };
56
+ surface: (indices) => {
57
+ let ptr;
58
+ alloc.data(indices)(x => { ptr = mod.surface_new(x.slice); })();
59
+ return resource({
60
+ nFaces: () => mod.surface_n_faces(ptr),
61
+ nHalfedges: () => mod.surface_n_halfedges(ptr),
62
+ h2f: (i) => mod.surface_h2f(ptr, i),
63
+ hNext: (i) => mod.surface_h_next(ptr, i),
64
+ hTwin: (i) => mod.surface_h_twin(ptr, i),
65
+ f2h: (i) => mod.surface_f2h(ptr, i),
66
+ geometry: (positions) => map(combine({
67
+ pPos: alloc.data(positions),
68
+ geom: alloc.struct(S.Geometry),
69
+ }), ({ pPos, geom }) => {
70
+ geom.value.mesh = ptr;
71
+ geom.value.data = pPos.slice;
72
+ return {
73
+ doubleArea: (i) => mod.surface_double_area(geom.ptr, i),
74
+ doubleAreas: (res = new Float32Array(indices.length / 3)) => withSlice(res, s => mod.surface_double_areas(geom.ptr, s)),
75
+ faceNormal: (f, res = new Float32Array(3)) => withSlice(res, s => mod.surface_face_normal(geom.ptr, f, s)),
76
+ faceNormals: (res = new Float32Array(indices.length)) => withSlice(res, s => mod.surface_face_normals(geom.ptr, s)),
77
+ internalAngles: (res = new Float32Array(indices.length)) => withSlice(res, s => mod.surface_internal_angles(geom.ptr, s)),
78
+ angleDefects: (res = new Float32Array(positions.length / 3)) => withSlice(res, s => mod.surface_angle_defects(geom.ptr, s)),
79
+ vertexNormalsAreaWeighted: (res = new Float32Array(positions.length)) => withSlice(res, s => mod.surface_vertex_normals_area_weighted(geom.ptr, s)),
80
+ vertexNormalsAngleWeighted: (res = new Float32Array(positions.length)) => withSlice(res, s => mod.surface_vertex_normals_angle_weighted(geom.ptr, s)),
81
+ };
82
+ })
83
+ }, () => mod.surface_free(ptr));
84
+ },
85
+ manifold: (indices) => {
86
+ let ptr;
87
+ alloc.data(indices)(x => { ptr = mod.manifold_new(x.slice); })();
58
88
  return resource({
59
- nFaces: () => mod.n_faces(ptr),
60
- nHalfedges: () => mod.n_halfedges(ptr),
61
- h2f: (i) => mod.h2f(ptr, i),
62
- hNext: (i) => mod.h_next(ptr, i),
63
- hTwin: (i) => mod.h_twin(ptr, i),
64
- f2h: (i) => mod.f2h(ptr, i),
65
- doubleArea: (i) => mod.double_area(ptr, i),
66
- doubleAreas: (res) => withResult(res, s => mod.double_areas(ptr, s.ptr)),
67
- faceNormals: (res) => withResult(res, s => mod.face_normals(ptr, s.ptr)),
68
- internalAngles: (res) => withResult(res, s => mod.internal_angles(ptr, s.ptr)),
69
- vertexNormalsAreaWeighted: (res) => withResult(res, s => mod.vertex_normals_area_weighted(ptr, s.ptr)),
70
- vertexNormalsAngleWeighted: (res) => withResult(res, s => mod.vertex_normals_angle_weighted(ptr, s.ptr)),
71
- angleDefects: (res) => withResult(res, s => mod.angle_defects(ptr, s.ptr)),
72
- }, () => mod.free_vertex_position_geometry(ptr));
73
- })
89
+ nFaces: () => mod.manifold_n_faces(ptr),
90
+ nHalfedges: () => mod.manifold_n_halfedges(ptr),
91
+ h2f: (i) => mod.manifold_h2f(ptr, i),
92
+ hNext: (i) => mod.manifold_h_next(ptr, i),
93
+ hTwin: (i) => mod.manifold_h_twin(ptr, i),
94
+ f2h: (i) => mod.manifold_f2h(ptr, i),
95
+ geometryF: (positions) => map(combine({
96
+ pPos: alloc.data(positions),
97
+ geom: alloc.struct(S.Geometry),
98
+ }), ({ pPos, geom }) => {
99
+ geom.value.mesh = ptr;
100
+ geom.value.data = pPos.slice;
101
+ return {
102
+ faceArea: (i) => mod.manifold_face_area_f(geom.ptr, i),
103
+ tracer: () => {
104
+ const t = mod.geodesic_tracer_f_new(geom.ptr);
105
+ const start = (p, tVec) => {
106
+ let res;
107
+ combine({
108
+ pt: alloc.struct(S.Point.F),
109
+ vec: alloc.data(tVec.data)
110
+ })(({ pt, vec }) => {
111
+ pt.value.type = PointType[p.type];
112
+ pt.value.index = p.index;
113
+ const trPtr = mod.geodesic_tracer_f_trace_start(t, ptr, pt.ptr, vec.slice);
114
+ const tr = view(S.Trace.Result.F, mod.memory.buffer, trPtr);
115
+ res = { point: fromPoint(tr.point), state: tr.state };
116
+ mod.geodesic_tracer_f_trace_result_free(trPtr);
117
+ })();
118
+ return res;
119
+ };
120
+ const next = (state) => {
121
+ const trPtr = mod.geodesic_tracer_f_trace_next(t, ptr, state);
122
+ mod.geodesic_tracer_f_trace_state_free(state);
123
+ const tr = view(S.Trace.Result.F, mod.memory.buffer, trPtr);
124
+ const res = { point: fromPoint(tr.point), state: tr.state };
125
+ mod.geodesic_tracer_f_trace_result_free(trPtr);
126
+ return res;
127
+ };
128
+ return resource({
129
+ ptr: t,
130
+ trace: function* (p, tVec) {
131
+ let res = start(p, tVec);
132
+ yield res.point;
133
+ while (res.state != 0) {
134
+ res = next(res.state);
135
+ yield res.point;
136
+ }
137
+ }
138
+ }, () => mod.geodesic_tracer_f_free(t));
139
+ },
140
+ signpost: () => {
141
+ const sp = mod.signpost_f_new(geom.ptr);
142
+ return resource({
143
+ flipToDelaunay: () => mod.signpost_f_flip_to_delaunay(sp),
144
+ traceAlongInput: (tracer, i) => {
145
+ const slice = mod.signpost_f_trace_along_input(sp, tracer, ptr, i);
146
+ const unpacked = unpackSlice(slice);
147
+ const points = view(array(S.Point.F, unpacked.len), mod.memory.buffer, unpacked.ptr).map(fromPoint);
148
+ mod.free_points_f(slice);
149
+ return points;
150
+ }
151
+ }, () => mod.signpost_f_free(sp));
152
+ }
153
+ };
154
+ }),
155
+ geometryD: (positions) => map(combine({
156
+ pPos: alloc.data(positions),
157
+ geom: alloc.struct(S.Geometry),
158
+ }), ({ pPos, geom }) => {
159
+ geom.value.mesh = ptr;
160
+ geom.value.data = pPos.slice;
161
+ return {
162
+ faceArea: (i) => mod.manifold_face_area_d(geom.ptr, i),
163
+ tracer: () => {
164
+ const t = mod.geodesic_tracer_d_new(geom.ptr);
165
+ const start = (p, tVec) => {
166
+ let res;
167
+ combine({
168
+ pt: alloc.struct(S.Point.D),
169
+ vec: alloc.data(tVec.data)
170
+ })(({ pt, vec }) => {
171
+ pt.value.type = PointType[p.type];
172
+ pt.value.index = p.index;
173
+ const trPtr = mod.geodesic_tracer_d_trace_start(t, ptr, pt.ptr, vec.slice);
174
+ const tr = view(S.Trace.Result.D, mod.memory.buffer, trPtr);
175
+ res = { point: fromPoint(tr.point), state: tr.state };
176
+ mod.geodesic_tracer_d_trace_result_free(trPtr);
177
+ })();
178
+ return res;
179
+ };
180
+ const next = (state) => {
181
+ const trPtr = mod.geodesic_tracer_d_trace_next(t, ptr, state);
182
+ mod.geodesic_tracer_d_trace_state_free(state);
183
+ const tr = view(S.Trace.Result.D, mod.memory.buffer, trPtr);
184
+ const res = { point: fromPoint(tr.point), state: tr.state };
185
+ mod.geodesic_tracer_d_trace_result_free(trPtr);
186
+ return res;
187
+ };
188
+ return resource({
189
+ ptr: t,
190
+ trace: function* (p, tVec) {
191
+ let res = start(p, tVec);
192
+ yield res.point;
193
+ while (res.state != 0) {
194
+ res = next(res.state);
195
+ yield res.point;
196
+ }
197
+ }
198
+ }, () => mod.geodesic_tracer_d_free(t));
199
+ },
200
+ signpost: () => {
201
+ const sp = mod.signpost_d_new(geom.ptr);
202
+ return resource({
203
+ flipToDelaunay: () => mod.signpost_d_flip_to_delaunay(sp),
204
+ traceAlongInput: (tracer, i) => {
205
+ const slice = mod.signpost_d_trace_along_input(sp, tracer, ptr, i);
206
+ const unpacked = unpackSlice(slice);
207
+ const points = view(array(S.Point.D, unpacked.len), mod.memory.buffer, unpacked.ptr).map(fromPoint);
208
+ mod.free_points_d(slice);
209
+ return points;
210
+ }
211
+ }, () => mod.signpost_d_free(sp));
212
+ }
213
+ };
214
+ }),
215
+ }, () => mod.manifold_free(ptr));
216
+ }
74
217
  };
75
218
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cgtk/gp",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "exports": {
@@ -12,12 +12,14 @@
12
12
  "**/*.wasm"
13
13
  ],
14
14
  "dependencies": {
15
- "@cgtk/geometry": "~0.0.19",
16
- "@cgtk/std": "~0.0.188"
15
+ "@cgtk/std": "~0.0.192",
16
+ "@cgtk/linalg": "~0.0.6"
17
17
  },
18
18
  "devDependencies": {
19
- "@types/bun": "^1.3.8",
20
- "@types/node": "^25.2.1",
19
+ "@cgtk/geometry": "~0.0.23",
20
+ "@types/bun": "^1.3.10",
21
+ "@types/node": "^25.5.0",
22
+ "npm-check-updates": "^19.6.3",
21
23
  "typescript": "^5.9.3"
22
24
  },
23
25
  "publishConfig": {
package/point.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ import type { Vec3 } from "@cgtk/linalg/types";
2
+ interface PointVertex {
3
+ type: "vertex";
4
+ index: number;
5
+ }
6
+ interface PointEdge {
7
+ type: "edge";
8
+ index: number;
9
+ t: number;
10
+ }
11
+ interface PointFace<T extends Float32Array | Float64Array> {
12
+ type: "face";
13
+ index: number;
14
+ p: Vec3<T>;
15
+ }
16
+ export type Point<T extends Float32Array | Float64Array> = PointVertex | PointEdge | PointFace<T>;
17
+ export declare const point: {
18
+ readonly vertex: (index: number) => PointVertex;
19
+ readonly edge: (index: number, t: number) => PointEdge;
20
+ readonly face: <T extends Float32Array | Float64Array>(index: number, p: Vec3<T>) => PointFace<T>;
21
+ };
22
+ export declare const PointType: {
23
+ readonly vertex: 0;
24
+ readonly edge: 1;
25
+ readonly face: 2;
26
+ };
27
+ export declare const from: <T extends Float32Array | Float64Array>({ type, index, data }: {
28
+ type: number;
29
+ index: number;
30
+ data: T;
31
+ }) => Point<T>;
32
+ export {};
package/point.js ADDED
@@ -0,0 +1,18 @@
1
+ import * as vec3 from "@cgtk/linalg/vec3";
2
+ export const point = {
3
+ vertex: (index) => ({ type: "vertex", index }),
4
+ edge: (index, t) => ({ type: "edge", index, t }),
5
+ face: (index, p) => ({ type: "face", index, p }),
6
+ };
7
+ export const PointType = {
8
+ vertex: 0,
9
+ edge: 1,
10
+ face: 2
11
+ };
12
+ export const from = ({ type, index, data }) => {
13
+ if (type == 0)
14
+ return point.vertex(index);
15
+ else if (type == 1)
16
+ return point.edge(index, data[0]);
17
+ return point.face(index, vec3.from(data.slice()));
18
+ };
package/struct.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export declare const Geometry: import("@cgtk/std/struct").Struct<readonly [readonly ["mesh", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["data", import("@cgtk/std/struct").Vec<BigUint64Array<ArrayBufferLike>, 1>]]>;
2
+ export declare const Point: {
3
+ readonly F: import("@cgtk/std/struct").Struct<readonly [readonly ["type", import("@cgtk/std/struct").Vec<Uint8Array<ArrayBufferLike>, 1>], readonly ["index", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["data", import("@cgtk/std/struct").Vec<Float32Array<ArrayBufferLike>, 3>]]>;
4
+ readonly D: import("@cgtk/std/struct").Struct<readonly [readonly ["type", import("@cgtk/std/struct").Vec<Uint8Array<ArrayBufferLike>, 1>], readonly ["index", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["data", import("@cgtk/std/struct").Vec<Float64Array<ArrayBufferLike>, 3>]]>;
5
+ };
6
+ export declare const Trace: {
7
+ readonly State: {
8
+ readonly F: import("@cgtk/std/struct").Struct<readonly [readonly ["f", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["p", import("@cgtk/std/struct").Vec<Float32Array<ArrayBufferLike>, 3>], readonly ["d_bary", import("@cgtk/std/struct").Vec<Float32Array<ArrayBufferLike>, 3>], readonly ["d_cart", import("@cgtk/std/struct").Vec<Float32Array<ArrayBufferLike>, 2>], readonly ["len", import("@cgtk/std/struct").Vec<Float32Array<ArrayBufferLike>, 1>]]>;
9
+ readonly D: import("@cgtk/std/struct").Struct<readonly [readonly ["f", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["p", import("@cgtk/std/struct").Vec<Float64Array<ArrayBufferLike>, 3>], readonly ["d_bary", import("@cgtk/std/struct").Vec<Float64Array<ArrayBufferLike>, 3>], readonly ["d_cart", import("@cgtk/std/struct").Vec<Float64Array<ArrayBufferLike>, 2>], readonly ["len", import("@cgtk/std/struct").Vec<Float64Array<ArrayBufferLike>, 1>]]>;
10
+ };
11
+ readonly Result: {
12
+ readonly F: import("@cgtk/std/struct").Struct<readonly [readonly ["point", import("@cgtk/std/struct").Struct<readonly [readonly ["type", import("@cgtk/std/struct").Vec<Uint8Array<ArrayBufferLike>, 1>], readonly ["index", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["data", import("@cgtk/std/struct").Vec<Float32Array<ArrayBufferLike>, 3>]]>], readonly ["state", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>]]>;
13
+ readonly D: import("@cgtk/std/struct").Struct<readonly [readonly ["point", import("@cgtk/std/struct").Struct<readonly [readonly ["type", import("@cgtk/std/struct").Vec<Uint8Array<ArrayBufferLike>, 1>], readonly ["index", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>], readonly ["data", import("@cgtk/std/struct").Vec<Float64Array<ArrayBufferLike>, 3>]]>], readonly ["state", import("@cgtk/std/struct").Vec<Uint32Array<ArrayBufferLike>, 1>]]>;
14
+ };
15
+ };
package/struct.js ADDED
@@ -0,0 +1,45 @@
1
+ import { struct, u32, u8, f32, f64, u64 } from "@cgtk/std/struct";
2
+ export const Geometry = struct([
3
+ ["mesh", u32()],
4
+ ["data", u64()]
5
+ ]);
6
+ export const Point = {
7
+ F: struct([
8
+ ["type", u8()],
9
+ ["index", u32()],
10
+ ["data", f32(3)]
11
+ ]),
12
+ D: struct([
13
+ ["type", u8()],
14
+ ["index", u32()],
15
+ ["data", f64(3)]
16
+ ])
17
+ };
18
+ export const Trace = {
19
+ State: {
20
+ F: struct([
21
+ ["f", u32()],
22
+ ["p", f32(3)],
23
+ ["d_bary", f32(3)],
24
+ ["d_cart", f32(2)],
25
+ ["len", f32()]
26
+ ]),
27
+ D: struct([
28
+ ["f", u32()],
29
+ ["p", f64(3)],
30
+ ["d_bary", f64(3)],
31
+ ["d_cart", f64(2)],
32
+ ["len", f64()]
33
+ ]),
34
+ },
35
+ Result: {
36
+ F: struct([
37
+ ["point", Point.F],
38
+ ["state", u32()]
39
+ ]),
40
+ D: struct([
41
+ ["point", Point.D],
42
+ ["state", u32()]
43
+ ])
44
+ }
45
+ };