@strategicprojects/rpic 0.13.0 → 0.14.0
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/README.md +40 -1
- package/index.d.ts +176 -0
- package/index.js +331 -20
- package/package.json +11 -5
- package/pkg/rpic_wasm_bg.wasm +0 -0
- package/pkg/rpic_wasm_geo.d.ts +99 -0
- package/pkg/rpic_wasm_geo.js +356 -0
- package/pkg/rpic_wasm_geo_bg.wasm +0 -0
- package/pkg/rpic_wasm_geo_bg.wasm.d.ts +14 -0
- package/pkg/rpic_wasm_math_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -76,13 +76,52 @@ call that asks for the other build rejects instead of silently reusing the
|
|
|
76
76
|
first build. In Node, pass the math artifact's bytes:
|
|
77
77
|
`ready(readFileSync(new URL('…/pkg/rpic_wasm_math_bg.wasm', import.meta.url)), { math: true })`.
|
|
78
78
|
|
|
79
|
+
### Maps (geopic: drawings as GeoJSON)
|
|
80
|
+
|
|
81
|
+
A third, opt-in build georeferences a drawing in the browser: the result is an
|
|
82
|
+
RFC 7946 `FeatureCollection` (WGS84) for Leaflet, MapLibre, OpenLayers…
|
|
83
|
+
The drawing is placed by `geo_lon`/`geo_lat`/`geo_scale`/`geo_bearing` in the
|
|
84
|
+
source, by control points, or by the options below (which override them) —
|
|
85
|
+
the contract is [docs/geopic.md](https://github.com/milkway/rpic-lang/blob/main/docs/geopic.md).
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
await rpic.ready(undefined, { geo: true }); // browser: fetches pkg/rpic_wasm_geo_bg.wasm
|
|
89
|
+
|
|
90
|
+
const { geojson, warnings, registration } = rpic.compileGeoJSON(
|
|
91
|
+
'geo_scale = 1000\narrow from Recife to Olinda\n"Recife" at Recife below',
|
|
92
|
+
{
|
|
93
|
+
anchor: [-34.8711, -8.0631],
|
|
94
|
+
features: { Recife: [-34.8711, -8.0631], Olinda: [-34.8553, -8.0089] },
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
L.geoJSON(geojson).addTo(map); // e.g. Leaflet
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`features` names points the source may use without defining them: names the
|
|
101
|
+
source defines are control points of its own geometry, the others are
|
|
102
|
+
injected as places (or invisible boxes, given a `bbox: [w, s, e, n]`, so
|
|
103
|
+
`Zone.n` follows the extent). Names must be pic labels (`/^[A-Z][A-Za-z0-9_]*$/`)
|
|
104
|
+
and are validated before anything compiles. Options: `frame` (`'enu'` |
|
|
105
|
+
`'mercator'`), `anchor`, `scale` (m per inch), `bearing` (° clockwise from
|
|
106
|
+
north), `features`, `flatten`, `viewScale`, `screenClasses`, `circuits`,
|
|
107
|
+
`texlabels`. A georeferencing failure throws a `GeoError` whose `info` is
|
|
108
|
+
`{ kind, message, hint }` (`no_registration`, `invalid_anchor`, …); pic errors
|
|
109
|
+
throw the usual error with `errorInfo`. Nothing is dropped silently: every loss
|
|
110
|
+
(an unsupported style, ignored `animate` timelines…) is in `warnings`, next to
|
|
111
|
+
the engine's own warnings; pic `print` lines are in `diagnostics`. Numeric
|
|
112
|
+
options must be finite (`scale`/`flatten`/`viewScale` > 0) or the call throws.
|
|
113
|
+
`geoToCanvas(registration, [[lon, lat], …])` maps points back onto the canvas.
|
|
114
|
+
In Node, pass the bytes of `pkg/rpic_wasm_geo_bg.wasm` to `ready(…, { geo: true })`.
|
|
115
|
+
|
|
79
116
|
## API
|
|
80
117
|
|
|
81
118
|
| Function | Description |
|
|
82
119
|
|----------|-------------|
|
|
83
|
-
| `ready(wasmInput?, {math?})` | Initialize WASM. Browser: no arg. Node: pass `.wasm` bytes/URL. `math: true` loads the math-enabled build; conflicting later calls reject. |
|
|
120
|
+
| `ready(wasmInput?, {math?, geo?})` | Initialize WASM. Browser: no arg. Node: pass `.wasm` bytes/URL. `math: true` loads the math-enabled build, `geo: true` the geo-enabled one; conflicting later calls reject. |
|
|
84
121
|
| `compile(src, {circuits?, texlabels?, scene?, flatten?, outline?})` | → `{ svg, animations, diagnostics, warnings, objects, places?, passthrough?, scene? }` (throws on a pic error with `errorInfo`; `places` = named `Label: position` points in SVG units, `passthrough` = troff `.` lines, each present only when the source has some). `scene: true` adds the device-independent resolved draw list ([docs/scene.md](https://github.com/milkway/rpic-lang/blob/main/docs/scene.md)); `flatten` (inches) delivers its curves as polylines. |
|
|
85
122
|
| `renderSvg(src, {circuits?, texlabels?})` | → SVG string. |
|
|
123
|
+
| `compileGeoJSON(src, {anchor?, scale?, bearing?, frame?, features?, …})` | Geo build only. → `{ geojson, warnings, diagnostics, registration, canvas }`; throws `GeoError` (`info.kind`) or a pic error. |
|
|
124
|
+
| `geoToCanvas(registration, points)` | Geo build only. WGS84 `[lon, lat]` points → canvas `[x, y]` inches. |
|
|
86
125
|
| `animate(root, animations, gsap)` | Build/play a GSAP timeline (`draw`/`fade`/`pop`). Browser only. |
|
|
87
126
|
|
|
88
127
|
Compile errors keep a readable `message` and expose structured data for editors:
|
package/index.d.ts
CHANGED
|
@@ -175,6 +175,11 @@ export interface Scene {
|
|
|
175
175
|
origin: [number, number];
|
|
176
176
|
};
|
|
177
177
|
source?: string;
|
|
178
|
+
/**
|
|
179
|
+
* the uniform factor the whole-picture rescale (`.PS <w>`, `maxpswid`/`maxpsht`)
|
|
180
|
+
* applied to the geometry; 1 when none acted. `vars` are pre-rescale.
|
|
181
|
+
*/
|
|
182
|
+
rescale: number;
|
|
178
183
|
/** final values of every variable (user + pic built-ins) */
|
|
179
184
|
vars: Record<string, number>;
|
|
180
185
|
/** named places (`Label: position`), evaluation order; empty when none */
|
|
@@ -240,6 +245,13 @@ export interface ReadyOptions {
|
|
|
240
245
|
* pass the math wasm bytes as `wasmInput`.
|
|
241
246
|
*/
|
|
242
247
|
math?: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* Load the geo-enabled wasm build (`pkg/rpic_wasm_geo_bg.wasm`), which adds
|
|
250
|
+
* `compileGeoJSON` / `geoToCanvas` (geopic: drawings as GeoJSON). Fetched
|
|
251
|
+
* only when requested; cannot be combined with `math`. In Node, pass the
|
|
252
|
+
* geo wasm bytes as `wasmInput`.
|
|
253
|
+
*/
|
|
254
|
+
geo?: boolean;
|
|
243
255
|
}
|
|
244
256
|
|
|
245
257
|
/**
|
|
@@ -257,3 +269,167 @@ export function compile(src: string, opts?: CompileOptions): Bundle;
|
|
|
257
269
|
|
|
258
270
|
/** Compile and return only the SVG string. */
|
|
259
271
|
export function renderSvg(src: string, opts?: CompileOptions): string;
|
|
272
|
+
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// geopic: pic drawings as GeoJSON (docs/geopic.md). Needs the geo build:
|
|
275
|
+
// `await ready(undefined, { geo: true })`.
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
|
|
278
|
+
/** `[west, south, east, north]`, degrees. */
|
|
279
|
+
export type GeoBBox = [number, number, number, number];
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* A named geographic feature the host knows about. The name must be a pic
|
|
283
|
+
* label (`/^[A-Z][A-Za-z0-9_]*$/`); anything else is rejected before
|
|
284
|
+
* compiling. With a `bbox` it is injected as an invisible box, so
|
|
285
|
+
* `Name.n`/`Name.e`/… follow its extent (compass corners are canvas
|
|
286
|
+
* directions).
|
|
287
|
+
*/
|
|
288
|
+
export interface GeoFeatureInput {
|
|
289
|
+
name: string;
|
|
290
|
+
lon: number;
|
|
291
|
+
lat: number;
|
|
292
|
+
bbox?: GeoBBox | null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* `features` in any of its accepted forms: `{ Name: [lon, lat] }`,
|
|
297
|
+
* `{ Name: [lon, lat, bbox] }`, `{ Name: { lon, lat, bbox? } }`, or an array
|
|
298
|
+
* of `{ name, lon, lat, bbox? }` objects / `[name, lon, lat, bbox?]` tuples.
|
|
299
|
+
*/
|
|
300
|
+
export type GeoFeatures =
|
|
301
|
+
| Record<string, [number, number] | [number, number, GeoBBox | null] | { lon: number; lat: number; bbox?: GeoBBox | null }>
|
|
302
|
+
| Array<GeoFeatureInput | [string, number, number] | [string, number, number, GeoBBox | null]>;
|
|
303
|
+
|
|
304
|
+
export interface GeoOptions {
|
|
305
|
+
/** load the native circuit-element library */
|
|
306
|
+
circuits?: boolean;
|
|
307
|
+
/** set `texlabels = 1` (the geo build has no math renderer: literal labels + a diagnostic) */
|
|
308
|
+
texlabels?: boolean;
|
|
309
|
+
/** projection frame; overrides `geo_frame` */
|
|
310
|
+
frame?: 'enu' | 'mercator';
|
|
311
|
+
/** `[lon, lat]` of the pic origin; overrides `geo_lon`/`geo_lat` */
|
|
312
|
+
anchor?: [number, number];
|
|
313
|
+
/** metres per authored inch; overrides `geo_scale` (default 100) */
|
|
314
|
+
scale?: number;
|
|
315
|
+
/** azimuth of the canvas +y axis, degrees clockwise from north; overrides `geo_bearing` */
|
|
316
|
+
bearing?: number;
|
|
317
|
+
/**
|
|
318
|
+
* Named features: those the source defines (places or labelled objects)
|
|
319
|
+
* are control points of its geometry; the others are injected as places
|
|
320
|
+
* (two-pass), so `arrow from Recife to Olinda` works without the source
|
|
321
|
+
* defining them.
|
|
322
|
+
*/
|
|
323
|
+
features?: GeoFeatures;
|
|
324
|
+
/** flattening tolerance for curves, inches (default `1e-3`) */
|
|
325
|
+
flatten?: number;
|
|
326
|
+
/** pixels per inch when the source sets `geo_px = 1` */
|
|
327
|
+
viewScale?: number;
|
|
328
|
+
/** `class` words marking screen-anchored items (default `['screen']`) */
|
|
329
|
+
screenClasses?: string[];
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** A non-fatal loss or substitution while georeferencing (never silent). */
|
|
333
|
+
export interface GeoWarning {
|
|
334
|
+
/**
|
|
335
|
+
* `unsupported_style`, `ignored`, `registration_residual`,
|
|
336
|
+
* `ignored_with_control_points`, `control_point_unresolved`,
|
|
337
|
+
* `control_point_overridden`, `unsupported_kind`, `densification_budget`,
|
|
338
|
+
* …; engine `scene_unsupported` diagnostics ride here too (with the
|
|
339
|
+
* `Diagnostic` keys instead of `id`/`span`).
|
|
340
|
+
*/
|
|
341
|
+
kind: string;
|
|
342
|
+
message: string;
|
|
343
|
+
/** the scene item concerned (`s<N>`), when there is one */
|
|
344
|
+
id?: string;
|
|
345
|
+
/**
|
|
346
|
+
* its source span, relative to your own source; `file: 'features'` marks a
|
|
347
|
+
* position inside the lines `compileGeoJSON` injected for `features`
|
|
348
|
+
*/
|
|
349
|
+
span?: { line: number; col: number; end_col: number; file?: string };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** The similarity canvas (inches) → Earth. */
|
|
353
|
+
export interface GeoRegistration {
|
|
354
|
+
frame: 'enu' | 'mercator';
|
|
355
|
+
/** geographic position of `origin` */
|
|
356
|
+
anchor: { lon: number; lat: number };
|
|
357
|
+
/** the canvas point (inches) that sits at `anchor` */
|
|
358
|
+
origin: [number, number];
|
|
359
|
+
/** metres per inch of the emitted geometry */
|
|
360
|
+
scale_m_per_in: number;
|
|
361
|
+
/** azimuth of the canvas +y axis, degrees clockwise from north */
|
|
362
|
+
bearing_deg: number;
|
|
363
|
+
method: 'anchor' | 'two_points' | 'helmert';
|
|
364
|
+
/** control points used by the fit (0 for a declared anchor) */
|
|
365
|
+
control_points: number;
|
|
366
|
+
/** RMS residual of the fit, metres (fits only) */
|
|
367
|
+
rms_m?: number;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export interface GeoJSONGeometry {
|
|
371
|
+
type: 'Point' | 'LineString' | 'Polygon' | 'MultiPoint' | 'MultiLineString' | 'MultiPolygon';
|
|
372
|
+
coordinates: unknown;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export interface GeoJSONFeature {
|
|
376
|
+
type: 'Feature';
|
|
377
|
+
geometry: GeoJSONGeometry | null;
|
|
378
|
+
/** simplestyle keys (`stroke`, `fill`, …) and `geopic:*` (docs/geopic.md) */
|
|
379
|
+
properties: Record<string, unknown>;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export interface GeoJSONFeatureCollection {
|
|
383
|
+
type: 'FeatureCollection';
|
|
384
|
+
features: GeoJSONFeature[];
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export interface GeoResult {
|
|
388
|
+
/** RFC 7946 FeatureCollection, WGS84 */
|
|
389
|
+
geojson: GeoJSONFeatureCollection;
|
|
390
|
+
/** engine warnings, then scene, then geopic ones — never silent */
|
|
391
|
+
warnings: (GeoWarning | Diagnostic)[];
|
|
392
|
+
/** lines emitted by pic `print` statements, plus engine notices (as in `Bundle`) */
|
|
393
|
+
diagnostics: string[];
|
|
394
|
+
registration: GeoRegistration;
|
|
395
|
+
/** what a host needs to write canvas positions back as source coordinates */
|
|
396
|
+
canvas: {
|
|
397
|
+
/** the whole-picture rescale (`.PS <width>`, `maxpswid`); 1 when none */
|
|
398
|
+
rescale: number;
|
|
399
|
+
/** the pic `scale` variable (source units per inch) */
|
|
400
|
+
scale: number;
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** A georeferencing error; `info.kind` is machine-readable. */
|
|
405
|
+
export class GeoError extends Error {
|
|
406
|
+
constructor(message: string, info: { kind: string; message: string; hint?: string });
|
|
407
|
+
info: {
|
|
408
|
+
/**
|
|
409
|
+
* `no_registration`, `invalid_scale`, `invalid_anchor`, `invalid_frame`,
|
|
410
|
+
* `invalid_scene`, `invalid_flatten`, `view_scale_required`,
|
|
411
|
+
* `degenerate_control_points`, `invalid_options` (option JSON of the
|
|
412
|
+
* wrong shape).
|
|
413
|
+
*/
|
|
414
|
+
kind: string;
|
|
415
|
+
message: string;
|
|
416
|
+
hint?: string;
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Georeference pic source as a GeoJSON FeatureCollection (WGS84). Needs the
|
|
422
|
+
* geo build (`ready(…, { geo: true })`). Throws a `CompileError` on a pic
|
|
423
|
+
* error, a `GeoError` on a georeferencing error, and a plain `Error` for an
|
|
424
|
+
* invalid feature name/shape (checked before anything compiles).
|
|
425
|
+
*/
|
|
426
|
+
export function compileGeoJSON(src: string, opts?: GeoOptions): GeoResult;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Canvas positions (inches) of WGS84 `[lon, lat]` points under a
|
|
430
|
+
* registration (as `compileGeoJSON` returned it). Needs the geo build.
|
|
431
|
+
*/
|
|
432
|
+
export function geoToCanvas(
|
|
433
|
+
registration: GeoRegistration | string,
|
|
434
|
+
points: [number, number][]
|
|
435
|
+
): [number, number][];
|
package/index.js
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
// Browser: await ready(); // wasm fetched automatically
|
|
4
4
|
// Node: await ready(fs.readFileSync(url)); // pass the .wasm bytes/URL
|
|
5
5
|
// Math: await ready(undefined, { math: true }); // texlabels typeset in-browser
|
|
6
|
+
// Maps: await ready(undefined, { geo: true }); // compileGeoJSON (drawing → GeoJSON)
|
|
6
7
|
import * as leanModule from './pkg/rpic_wasm.js';
|
|
7
8
|
|
|
9
|
+
// display names of the three builds, keyed by ready()'s choice
|
|
10
|
+
const BUILDS = { lean: 'lean', math: 'math-enabled', geo: 'geo-enabled' };
|
|
11
|
+
|
|
8
12
|
let initPromise = null;
|
|
9
|
-
let wasm = null; // the initialized glue module (lean or
|
|
10
|
-
let
|
|
13
|
+
let wasm = null; // the initialized glue module (lean, math or geo)
|
|
14
|
+
let initBuild = null; // 'lean' | 'math' | 'geo' while an init is pending/done
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* Initialize the WebAssembly module (idempotent; concurrent calls share one
|
|
@@ -16,29 +20,38 @@ let initMath = null;
|
|
|
16
20
|
*
|
|
17
21
|
* Pass `{ math: true }` to load the math-enabled build instead: it bundles
|
|
18
22
|
* the RaTeX renderer so `texlabels` sources typeset `$…$` labels exactly like
|
|
19
|
-
* the native CLI.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
23
|
+
* the native CLI. Pass `{ geo: true }` for the geo-enabled build, which adds
|
|
24
|
+
* `compileGeoJSON`/`geoToCanvas` (geopic: drawings as GeoJSON). Either extra
|
|
25
|
+
* glue + wasm is only fetched when requested, so the lean fast path stays
|
|
26
|
+
* untouched; the two cannot be combined. The choice is fixed by the first
|
|
27
|
+
* successful (or in-flight) call; later calls asking for another build
|
|
22
28
|
* reject. A *failed* init (bad bytes, fetch error) clears the slot so
|
|
23
29
|
* `ready()` can be retried. In Node, pass the bytes of
|
|
24
|
-
* `pkg/rpic_wasm_math_bg.wasm` along with it.
|
|
30
|
+
* `pkg/rpic_wasm_math_bg.wasm` / `pkg/rpic_wasm_geo_bg.wasm` along with it.
|
|
25
31
|
*/
|
|
26
32
|
export function ready(wasmInput, opts = {}) {
|
|
27
|
-
|
|
33
|
+
if (opts.math && opts.geo) {
|
|
34
|
+
return Promise.reject(new Error('rpic: ready() cannot load the math and geo builds together; pick one'));
|
|
35
|
+
}
|
|
36
|
+
const wanted = opts.math ? 'math' : opts.geo ? 'geo' : 'lean';
|
|
28
37
|
if (initPromise) {
|
|
29
|
-
if (
|
|
30
|
-
const current = initMath ? 'math-enabled' : 'lean';
|
|
31
|
-
const requested = wantsMath ? 'math-enabled' : 'lean';
|
|
38
|
+
if (initBuild !== wanted) {
|
|
32
39
|
return Promise.reject(
|
|
33
|
-
new Error(
|
|
40
|
+
new Error(
|
|
41
|
+
`rpic: ready() already initialized the ${BUILDS[initBuild]} build; cannot switch to ${BUILDS[wanted]}`
|
|
42
|
+
)
|
|
34
43
|
);
|
|
35
44
|
}
|
|
36
45
|
return initPromise;
|
|
37
46
|
}
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
initBuild = wanted;
|
|
48
|
+
const load =
|
|
49
|
+
wanted === 'math'
|
|
50
|
+
? import('./pkg/rpic_wasm_math.js')
|
|
51
|
+
: wanted === 'geo'
|
|
52
|
+
? import('./pkg/rpic_wasm_geo.js')
|
|
53
|
+
: Promise.resolve(leanModule);
|
|
54
|
+
const attempt = load
|
|
42
55
|
.then(async (mod) => {
|
|
43
56
|
await mod.default(wasmInput === undefined ? undefined : { module_or_path: wasmInput });
|
|
44
57
|
wasm = mod;
|
|
@@ -48,7 +61,7 @@ export function ready(wasmInput, opts = {}) {
|
|
|
48
61
|
// (only if it is still ours) so the next ready() starts fresh
|
|
49
62
|
if (initPromise === attempt) {
|
|
50
63
|
initPromise = null;
|
|
51
|
-
|
|
64
|
+
initBuild = null;
|
|
52
65
|
}
|
|
53
66
|
throw e;
|
|
54
67
|
});
|
|
@@ -88,19 +101,317 @@ export function compile(src, opts = {}) {
|
|
|
88
101
|
: wasm.compile(src);
|
|
89
102
|
const out = JSON.parse(json);
|
|
90
103
|
if (out.error) {
|
|
91
|
-
|
|
92
|
-
err.errorInfo = out.error_info;
|
|
93
|
-
err.warnings = out.warnings ?? [];
|
|
94
|
-
throw err;
|
|
104
|
+
throw compileError(out);
|
|
95
105
|
}
|
|
96
106
|
return out;
|
|
97
107
|
}
|
|
98
108
|
|
|
109
|
+
/** The Error a pic error becomes: `.errorInfo` (a Diagnostic) + `.warnings`. */
|
|
110
|
+
function compileError(out) {
|
|
111
|
+
const err = new Error(out.error);
|
|
112
|
+
err.errorInfo = out.error_info;
|
|
113
|
+
err.warnings = out.warnings ?? [];
|
|
114
|
+
return err;
|
|
115
|
+
}
|
|
116
|
+
|
|
99
117
|
/** Compile and return just the SVG string. */
|
|
100
118
|
export function renderSvg(src, opts) {
|
|
101
119
|
return compile(src, opts).svg;
|
|
102
120
|
}
|
|
103
121
|
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// geopic: pic drawings as GeoJSON (docs/geopic.md). Needs the geo build:
|
|
124
|
+
// `await ready(undefined, { geo: true })`. Mirrors Python's `rpic.geo`.
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* A georeferencing error. `.message` is the readable text; `.info` is the
|
|
129
|
+
* structured `{ kind, message, hint? }` (`no_registration`, `invalid_anchor`,
|
|
130
|
+
* `invalid_frame`, `invalid_options`, …).
|
|
131
|
+
*/
|
|
132
|
+
export class GeoError extends Error {
|
|
133
|
+
constructor(message, info) {
|
|
134
|
+
super(message);
|
|
135
|
+
this.name = 'GeoError';
|
|
136
|
+
this.info = info;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// pic labels: an uppercase letter, then letters, digits or underscores.
|
|
141
|
+
// Feature names are written into pic source, so anything else is rejected
|
|
142
|
+
// outright — never interpolated.
|
|
143
|
+
const LABEL = /^[A-Z][A-Za-z0-9_]*$/;
|
|
144
|
+
const FORMS =
|
|
145
|
+
'rpic: features must be a {name: [lon, lat]} / {name: {lon, lat, bbox?}} object, ' +
|
|
146
|
+
'or an array of {name, lon, lat, bbox?} objects or [name, lon, lat, bbox?] tuples';
|
|
147
|
+
|
|
148
|
+
function featureLabel(name) {
|
|
149
|
+
const s = String(name);
|
|
150
|
+
if (!LABEL.test(s)) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`rpic: feature name ${JSON.stringify(s)} is not a pic label (an uppercase letter followed by letters, digits or underscores)`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return s;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function featureCoord(v, what) {
|
|
159
|
+
if (typeof v !== 'number' || !Number.isFinite(v)) {
|
|
160
|
+
throw new Error(`rpic: feature ${what} must be a finite number, got ${JSON.stringify(v) ?? String(v)}`);
|
|
161
|
+
}
|
|
162
|
+
return v;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function featureBbox(name, bbox) {
|
|
166
|
+
if (bbox === undefined || bbox === null) return null;
|
|
167
|
+
if (!Array.isArray(bbox) || bbox.length !== 4) {
|
|
168
|
+
throw new Error(`rpic: feature ${JSON.stringify(name)}: bbox must be [west, south, east, north]`);
|
|
169
|
+
}
|
|
170
|
+
return bbox.map((v) => featureCoord(v, `${name} bbox`));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function oneFeature(name, pos) {
|
|
174
|
+
const n = featureLabel(name);
|
|
175
|
+
if (Array.isArray(pos)) {
|
|
176
|
+
if (pos.length !== 2 && pos.length !== 3) throw new Error(FORMS);
|
|
177
|
+
return { name: n, lon: featureCoord(pos[0], `${n} lon`), lat: featureCoord(pos[1], `${n} lat`), bbox: featureBbox(n, pos[2]) };
|
|
178
|
+
}
|
|
179
|
+
if (pos && typeof pos === 'object') {
|
|
180
|
+
return { name: n, lon: featureCoord(pos.lon, `${n} lon`), lat: featureCoord(pos.lat, `${n} lat`), bbox: featureBbox(n, pos.bbox) };
|
|
181
|
+
}
|
|
182
|
+
throw new Error(FORMS);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** `features` in any accepted form → `[{name, lon, lat, bbox|null}]`. */
|
|
186
|
+
function normalizeFeatures(features) {
|
|
187
|
+
if (features === undefined || features === null) return [];
|
|
188
|
+
if (Array.isArray(features)) {
|
|
189
|
+
const out = features.map((item) => {
|
|
190
|
+
if (Array.isArray(item)) {
|
|
191
|
+
if (item.length !== 3 && item.length !== 4) throw new Error(FORMS);
|
|
192
|
+
if (typeof item[0] !== 'string') throw new Error(`${FORMS} (name is required)`);
|
|
193
|
+
return oneFeature(item[0], item.slice(1));
|
|
194
|
+
}
|
|
195
|
+
if (item && typeof item === 'object') {
|
|
196
|
+
if (typeof item.name !== 'string') throw new Error(`${FORMS} (name is required)`);
|
|
197
|
+
return oneFeature(item.name, item);
|
|
198
|
+
}
|
|
199
|
+
throw new Error(FORMS);
|
|
200
|
+
});
|
|
201
|
+
return unique(out);
|
|
202
|
+
}
|
|
203
|
+
if (typeof features === 'object') {
|
|
204
|
+
return Object.entries(features).map(([name, pos]) => oneFeature(name, pos));
|
|
205
|
+
}
|
|
206
|
+
throw new Error(FORMS);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Reject a name given twice: which position would win is not obvious. */
|
|
210
|
+
function unique(feats) {
|
|
211
|
+
const seen = new Set();
|
|
212
|
+
for (const f of feats) {
|
|
213
|
+
if (seen.has(f.name)) throw new Error(`rpic: feature ${JSON.stringify(f.name)} is given more than once`);
|
|
214
|
+
seen.add(f.name);
|
|
215
|
+
}
|
|
216
|
+
return feats;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Re-base one position (`line`/`file`) past the `k` prelude lines. A
|
|
221
|
+
* position *inside* the prelude is not the caller's: it is tagged
|
|
222
|
+
* `file: 'features'` (`line` stays relative to the prelude).
|
|
223
|
+
*/
|
|
224
|
+
function rebaseLine(d, k) {
|
|
225
|
+
if (!k || !d || typeof d !== 'object' || d.file != null) return;
|
|
226
|
+
if (!Number.isInteger(d.line) || d.line < 1) return;
|
|
227
|
+
if (d.line > k) d.line -= k;
|
|
228
|
+
else d.file = 'features';
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Shift warnings back by the `k` prelude lines the host prepended, so
|
|
233
|
+
* positions refer to the caller's own source (positions inside an
|
|
234
|
+
* include/library carry a `file` and are left alone).
|
|
235
|
+
*/
|
|
236
|
+
function rebase(out, k) {
|
|
237
|
+
if (!k) return out;
|
|
238
|
+
for (const w of out.warnings ?? []) {
|
|
239
|
+
if (w.span && typeof w.span === 'object') rebaseLine(w.span, k);
|
|
240
|
+
else rebaseLine(w, k);
|
|
241
|
+
}
|
|
242
|
+
return out;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function geoWasm() {
|
|
246
|
+
ensure();
|
|
247
|
+
if (typeof wasm.compile_geo !== 'function') {
|
|
248
|
+
throw new Error('rpic: compileGeoJSON needs the geo-enabled build: `await ready(undefined, { geo: true })`');
|
|
249
|
+
}
|
|
250
|
+
return wasm;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** One native pass, diagnostics re-based by `k` lines. */
|
|
254
|
+
function geoPass(src, k, geoOpts, opts) {
|
|
255
|
+
const out = JSON.parse(geoWasm().compile_geo(src, !!opts.circuits, !!opts.texlabels, JSON.stringify(geoOpts)));
|
|
256
|
+
if (out.error_info) {
|
|
257
|
+
const err = compileError(out);
|
|
258
|
+
rebaseLine(err.errorInfo, k);
|
|
259
|
+
throw err;
|
|
260
|
+
}
|
|
261
|
+
if (out.geo_error) throw new GeoError(out.error, out.geo_error);
|
|
262
|
+
return rebase(out, k);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** 9 significant digits, like `%.9g` (the pic lexer reads exponents). */
|
|
266
|
+
const num = (x) => String(Number(x.toPrecision(9)));
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* pic statements defining every feature at its position, in the source's own
|
|
270
|
+
* units (pic `scale`, before the whole-picture `rescale`). A feature with a
|
|
271
|
+
* bbox becomes an invisible labelled box spanning the axis-aligned canvas
|
|
272
|
+
* extent of its four corners; a point feature a plain place. Names were
|
|
273
|
+
* validated by `featureLabel` — nothing else reaches the source.
|
|
274
|
+
*/
|
|
275
|
+
function prelude(registration, canvas, feats) {
|
|
276
|
+
const units = (canvas.scale ?? 1) / (canvas.rescale ?? 1); // source units per emitted inch
|
|
277
|
+
const pts = [];
|
|
278
|
+
for (const f of feats) {
|
|
279
|
+
pts.push([f.lon, f.lat]);
|
|
280
|
+
if (f.bbox) {
|
|
281
|
+
const [w, s, e, n] = f.bbox;
|
|
282
|
+
pts.push([w, s], [e, s], [e, n], [w, n]);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const canvasPts = geoToCanvas(registration, pts);
|
|
286
|
+
let i = 0;
|
|
287
|
+
const lines = feats.map((f) => {
|
|
288
|
+
const [x, y] = canvasPts[i++];
|
|
289
|
+
const at = `(${num(x * units)}, ${num(y * units)})`;
|
|
290
|
+
if (!f.bbox) return `${f.name}: ${at}`;
|
|
291
|
+
const corners = canvasPts.slice(i, i + 4);
|
|
292
|
+
i += 4;
|
|
293
|
+
const xs = corners.map((c) => c[0]);
|
|
294
|
+
const ys = corners.map((c) => c[1]);
|
|
295
|
+
const wid = (Math.max(...xs) - Math.min(...xs)) * units;
|
|
296
|
+
const ht = (Math.max(...ys) - Math.min(...ys)) * units;
|
|
297
|
+
return `${f.name}: box invis wid ${num(wid)} ht ${num(ht)} at ${at}`;
|
|
298
|
+
});
|
|
299
|
+
return lines.join('\n') + '\n';
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Two passes. Features the source itself defines (as places or labelled
|
|
304
|
+
* objects) are control points of the source's own geometry; the others are
|
|
305
|
+
* injected — placed by the registration of a first pass — as places or
|
|
306
|
+
* invisible boxes, then everything is georeferenced together.
|
|
307
|
+
*/
|
|
308
|
+
function compileWithFeatures(src, feats, base, opts) {
|
|
309
|
+
const names = new Set(feats.map((f) => f.name));
|
|
310
|
+
const k = feats.length;
|
|
311
|
+
const placeholders = feats.map((f) => `${f.name}: (0, 0)\n`).join('');
|
|
312
|
+
// which names does the source define? their definitions sit after the
|
|
313
|
+
// placeholder lines (a span is relative to the caller's text + prelude)
|
|
314
|
+
let scene;
|
|
315
|
+
try {
|
|
316
|
+
scene = compile(placeholders + src, { circuits: opts.circuits, texlabels: opts.texlabels, scene: true }).scene;
|
|
317
|
+
} catch (e) {
|
|
318
|
+
rebaseLine(e.errorInfo, k);
|
|
319
|
+
throw e;
|
|
320
|
+
}
|
|
321
|
+
const defined = new Set();
|
|
322
|
+
for (const p of [...(scene.places ?? []), ...(scene.items ?? [])]) {
|
|
323
|
+
if (names.has(p.label) && (p.span?.line ?? 0) > k) defined.add(p.label);
|
|
324
|
+
}
|
|
325
|
+
const own = feats.filter((f) => defined.has(f.name));
|
|
326
|
+
const inject = feats.filter((f) => !defined.has(f.name));
|
|
327
|
+
// pass 1: the registration — declared anchor, or the source's control
|
|
328
|
+
// points, the source-defined features among them
|
|
329
|
+
const first = geoPass(placeholders + src, k, { ...base, features: own }, opts);
|
|
330
|
+
if (!inject.length) return first;
|
|
331
|
+
const pre = prelude(first.registration, first.canvas, inject);
|
|
332
|
+
const out = geoPass(pre + src, inject.length, { ...base, features: feats }, opts);
|
|
333
|
+
if (first.registration.method === 'anchor' && first.registration.control_points === 0) {
|
|
334
|
+
// the injected features were placed *by* the declared values; the second
|
|
335
|
+
// pass's "declared values ignored" would blame the source
|
|
336
|
+
out.warnings = out.warnings.filter((w) => w.kind !== 'ignored_with_control_points');
|
|
337
|
+
}
|
|
338
|
+
return out;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Numeric options are checked here: `JSON.stringify` would turn NaN/Infinity
|
|
343
|
+
* into `null`, which the wasm reads as "not given" — a silent fallback.
|
|
344
|
+
*/
|
|
345
|
+
function checkGeoOptions(opts) {
|
|
346
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
347
|
+
for (const key of ['scale', 'flatten', 'viewScale']) {
|
|
348
|
+
if (opts[key] !== undefined && !(finite(opts[key]) && opts[key] > 0)) {
|
|
349
|
+
throw new Error(`rpic: ${key} must be a positive finite number`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (opts.bearing !== undefined && !finite(opts.bearing)) {
|
|
353
|
+
throw new Error('rpic: bearing must be a finite number (degrees)');
|
|
354
|
+
}
|
|
355
|
+
if (
|
|
356
|
+
opts.anchor !== undefined &&
|
|
357
|
+
!(Array.isArray(opts.anchor) && opts.anchor.length === 2 && opts.anchor.every(finite))
|
|
358
|
+
) {
|
|
359
|
+
throw new Error('rpic: anchor must be [lon, lat], two finite numbers');
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Georeference pic source: `{ geojson, warnings, diagnostics, registration,
|
|
365
|
+
* canvas }`.
|
|
366
|
+
* Needs the geo build (`await ready(undefined, { geo: true })`).
|
|
367
|
+
*
|
|
368
|
+
* `frame` (`'enu'` | `'mercator'`), `anchor` `[lon, lat]`, `scale` (metres per
|
|
369
|
+
* inch), `bearing` (degrees clockwise from north), `viewScale` (px per inch
|
|
370
|
+
* under `geo_px = 1`) and `screenClasses` override the source's `geo_*`
|
|
371
|
+
* variables; `flatten` is the curve tolerance (inches, default `1e-3`).
|
|
372
|
+
*
|
|
373
|
+
* `features` names points the source may use without defining them
|
|
374
|
+
* (`arrow from Recife to Olinda`): features the source does define act as
|
|
375
|
+
* control points of its own geometry; the others are projected by a first
|
|
376
|
+
* pass's registration and injected as places — invisible labelled boxes when
|
|
377
|
+
* they have a `bbox`, so `Name.n`/`Name.e` follow its extent — before the
|
|
378
|
+
* final pass. Diagnostics keep the caller's line numbers.
|
|
379
|
+
*
|
|
380
|
+
* Throws an `Error` with `.errorInfo` on a pic error (like `compile`) and a
|
|
381
|
+
* `GeoError` (`.info = { kind, message, hint }`) on a georeferencing error.
|
|
382
|
+
*/
|
|
383
|
+
export function compileGeoJSON(src, opts = {}) {
|
|
384
|
+
geoWasm();
|
|
385
|
+
checkGeoOptions(opts);
|
|
386
|
+
const feats = normalizeFeatures(opts.features);
|
|
387
|
+
const base = {
|
|
388
|
+
frame: opts.frame,
|
|
389
|
+
anchor: opts.anchor,
|
|
390
|
+
scale: opts.scale,
|
|
391
|
+
bearing: opts.bearing,
|
|
392
|
+
flatten: opts.flatten,
|
|
393
|
+
view_scale: opts.viewScale,
|
|
394
|
+
screen_classes: opts.screenClasses,
|
|
395
|
+
};
|
|
396
|
+
return feats.length
|
|
397
|
+
? compileWithFeatures(src, feats, base, opts)
|
|
398
|
+
: geoPass(src, 0, { ...base, features: [] }, opts);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Canvas positions (inches) of WGS84 `[lon, lat]` points under a
|
|
403
|
+
* registration (as `compileGeoJSON` returned it). Needs the geo build.
|
|
404
|
+
* @param {object | string} registration
|
|
405
|
+
* @param {[number, number][]} points
|
|
406
|
+
* @returns {[number, number][]}
|
|
407
|
+
*/
|
|
408
|
+
export function geoToCanvas(registration, points) {
|
|
409
|
+
const reg = typeof registration === 'string' ? registration : JSON.stringify(registration);
|
|
410
|
+
const out = JSON.parse(geoWasm().geo_to_canvas(reg, JSON.stringify(points)));
|
|
411
|
+
if (!Array.isArray(out)) throw new GeoError(out.error, out.geo_error);
|
|
412
|
+
return out;
|
|
413
|
+
}
|
|
414
|
+
|
|
104
415
|
// The GSAP player lives in player.js — a zero-import module, so consumers
|
|
105
416
|
// with pre-rendered SVG can `import { animate } from '…/player.js'` and pull
|
|
106
417
|
// in nothing wasm-related. Re-exported here to keep the one-stop API.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strategicprojects/rpic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "The pic graphics language compiled to SVG with animation manifests, via WebAssembly. Browser + Node.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"default": "./player.js"
|
|
17
17
|
},
|
|
18
18
|
"./pkg/rpic_wasm_bg.wasm": "./pkg/rpic_wasm_bg.wasm",
|
|
19
|
-
"./pkg/rpic_wasm_math_bg.wasm": "./pkg/rpic_wasm_math_bg.wasm"
|
|
19
|
+
"./pkg/rpic_wasm_math_bg.wasm": "./pkg/rpic_wasm_math_bg.wasm",
|
|
20
|
+
"./pkg/rpic_wasm_geo_bg.wasm": "./pkg/rpic_wasm_geo_bg.wasm"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
22
23
|
"index.js",
|
|
@@ -31,16 +32,21 @@
|
|
|
31
32
|
"pkg/rpic_wasm_math.d.ts",
|
|
32
33
|
"pkg/rpic_wasm_math_bg.wasm",
|
|
33
34
|
"pkg/rpic_wasm_math_bg.wasm.d.ts",
|
|
35
|
+
"pkg/rpic_wasm_geo.js",
|
|
36
|
+
"pkg/rpic_wasm_geo.d.ts",
|
|
37
|
+
"pkg/rpic_wasm_geo_bg.wasm",
|
|
38
|
+
"pkg/rpic_wasm_geo_bg.wasm.d.ts",
|
|
34
39
|
"README.md"
|
|
35
40
|
],
|
|
36
41
|
"scripts": {
|
|
37
42
|
"build:wasm:lean": "wasm-pack build ../../crates/wasm --target web --out-dir ../../bindings/js/pkg",
|
|
38
43
|
"build:wasm:math": "wasm-pack build ../../crates/wasm --target web --out-dir ../../bindings/js/pkg --out-name rpic_wasm_math -- --features math",
|
|
39
|
-
"build:wasm": "
|
|
44
|
+
"build:wasm:geo": "wasm-pack build ../../crates/wasm --target web --out-dir ../../bindings/js/pkg --out-name rpic_wasm_geo -- --features geo",
|
|
45
|
+
"build:wasm": "npm run build:wasm:lean && npm run build:wasm:math && npm run build:wasm:geo",
|
|
40
46
|
"prepack": "npm run build:wasm",
|
|
41
|
-
"test": "node test/smoke.mjs && node test/smoke-math.mjs"
|
|
47
|
+
"test": "node test/smoke.mjs && node test/smoke-math.mjs && node test/smoke-geo.mjs"
|
|
42
48
|
},
|
|
43
|
-
"keywords": ["pic", "svg", "diagram", "graphics", "wasm", "gsap", "animation", "circuits"],
|
|
49
|
+
"keywords": ["pic", "svg", "diagram", "graphics", "wasm", "gsap", "animation", "circuits", "geojson", "maps"],
|
|
44
50
|
"author": "André Leite <leite@de.ufpe.br>",
|
|
45
51
|
"license": "BSD-2-Clause",
|
|
46
52
|
"repository": {
|
package/pkg/rpic_wasm_bg.wasm
CHANGED
|
Binary file
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Compile pic source to a JSON `{svg, animations, diagnostics, warnings}`
|
|
6
|
+
* bundle (or `{error, error_info}`).
|
|
7
|
+
*/
|
|
8
|
+
export function compile(src: string): string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Like [`compile`], but with the native circuit-element library loaded
|
|
12
|
+
* (so `resistor`, `and_gate`, … are available). Loaded as an option, not
|
|
13
|
+
* prepended text: diagnostic positions stay relative to `src`.
|
|
14
|
+
*/
|
|
15
|
+
export function compile_circuits(src: string): string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Georeference pic source: `{"geojson": FeatureCollection, "warnings":
|
|
19
|
+
* [...], "diagnostics": [...], "registration": {...}, "canvas": {"rescale",
|
|
20
|
+
* "scale"}}`, or
|
|
21
|
+
* `{"error", "error_info"}` on a pic error, or `{"error", "geo_error":
|
|
22
|
+
* {kind, message, hint}}` on a georeferencing error (bad options included).
|
|
23
|
+
*
|
|
24
|
+
* `opts_json` is a JSON object (or empty string) with the optional keys
|
|
25
|
+
* `frame` (`"enu"` | `"mercator"`), `anchor` (`[lon, lat]`), `scale`
|
|
26
|
+
* (metres per inch), `bearing` (degrees clockwise from north), `features`
|
|
27
|
+
* (`[{name, lon, lat, bbox?}]`, control points by label), `flatten`
|
|
28
|
+
* (inches), `view_scale` (px per inch under `geo_px = 1`) and
|
|
29
|
+
* `screen_classes`. Each overrides the corresponding `geo_*` variable of
|
|
30
|
+
* the source. Animations cannot ride into GeoJSON: a source with `animate`
|
|
31
|
+
* statements adds an `ignored` warning.
|
|
32
|
+
*/
|
|
33
|
+
export function compile_geo(src: string, circuits: boolean, texlabels: boolean, opts_json: string): string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Like [`compile_with`], but the bundle also carries the device-independent
|
|
37
|
+
* `scene` draw list (docs/scene.md); `flatten` (inches) delivers curves as
|
|
38
|
+
* polylines. The plain entry points above stay byte-identical — the scene is
|
|
39
|
+
* computed only here.
|
|
40
|
+
*/
|
|
41
|
+
export function compile_scene(src: string, circuits: boolean, texlabels: boolean, flatten: number | null | undefined, outline: boolean): string;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Like [`compile`], with options: `circuits` loads the circuit-element
|
|
45
|
+
* library; `texlabels` sets `texlabels = 1` so `$…$` labels are typeset as
|
|
46
|
+
* TeX math. Note: the default wasm build ships without the math renderer
|
|
47
|
+
* (size budget), so with `texlabels` the labels fall back to literal text
|
|
48
|
+
* and a diagnostic — use the math-enabled build (`--features math`, the
|
|
49
|
+
* `rpic_wasm_math` npm artifact) to typeset them.
|
|
50
|
+
*/
|
|
51
|
+
export function compile_with(src: string, circuits: boolean, texlabels: boolean): string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Canvas positions (inches) of WGS84 points under a registration (as
|
|
55
|
+
* `compile_geo` returned it): `points_json` is `[[lon, lat], …]`; returns
|
|
56
|
+
* `[[x, y], …]`, or `{"error", "geo_error"}` when either input does not
|
|
57
|
+
* parse. The host uses it to place features before compiling (two-pass
|
|
58
|
+
* feature injection, see `bindings/js/index.js`).
|
|
59
|
+
*/
|
|
60
|
+
export function geo_to_canvas(registration_json: string, points_json: string): string;
|
|
61
|
+
|
|
62
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
63
|
+
|
|
64
|
+
export interface InitOutput {
|
|
65
|
+
readonly memory: WebAssembly.Memory;
|
|
66
|
+
readonly compile_geo: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
67
|
+
readonly geo_to_canvas: (a: number, b: number, c: number, d: number) => [number, number];
|
|
68
|
+
readonly compile: (a: number, b: number) => [number, number];
|
|
69
|
+
readonly compile_circuits: (a: number, b: number) => [number, number];
|
|
70
|
+
readonly compile_scene: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
71
|
+
readonly compile_with: (a: number, b: number, c: number, d: number) => [number, number];
|
|
72
|
+
readonly __wbindgen_externrefs: WebAssembly.Table;
|
|
73
|
+
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
74
|
+
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
75
|
+
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
76
|
+
readonly __wbindgen_start: () => void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Instantiates the given `module`, which can either be bytes or
|
|
83
|
+
* a precompiled `WebAssembly.Module`.
|
|
84
|
+
*
|
|
85
|
+
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
|
86
|
+
*
|
|
87
|
+
* @returns {InitOutput}
|
|
88
|
+
*/
|
|
89
|
+
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
93
|
+
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
94
|
+
*
|
|
95
|
+
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
|
96
|
+
*
|
|
97
|
+
* @returns {Promise<InitOutput>}
|
|
98
|
+
*/
|
|
99
|
+
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/* @ts-self-types="./rpic_wasm_geo.d.ts" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compile pic source to a JSON `{svg, animations, diagnostics, warnings}`
|
|
5
|
+
* bundle (or `{error, error_info}`).
|
|
6
|
+
* @param {string} src
|
|
7
|
+
* @returns {string}
|
|
8
|
+
*/
|
|
9
|
+
export function compile(src) {
|
|
10
|
+
let deferred2_0;
|
|
11
|
+
let deferred2_1;
|
|
12
|
+
try {
|
|
13
|
+
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
14
|
+
const len0 = WASM_VECTOR_LEN;
|
|
15
|
+
const ret = wasm.compile(ptr0, len0);
|
|
16
|
+
deferred2_0 = ret[0];
|
|
17
|
+
deferred2_1 = ret[1];
|
|
18
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
19
|
+
} finally {
|
|
20
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Like [`compile`], but with the native circuit-element library loaded
|
|
26
|
+
* (so `resistor`, `and_gate`, … are available). Loaded as an option, not
|
|
27
|
+
* prepended text: diagnostic positions stay relative to `src`.
|
|
28
|
+
* @param {string} src
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
export function compile_circuits(src) {
|
|
32
|
+
let deferred2_0;
|
|
33
|
+
let deferred2_1;
|
|
34
|
+
try {
|
|
35
|
+
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
36
|
+
const len0 = WASM_VECTOR_LEN;
|
|
37
|
+
const ret = wasm.compile_circuits(ptr0, len0);
|
|
38
|
+
deferred2_0 = ret[0];
|
|
39
|
+
deferred2_1 = ret[1];
|
|
40
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
41
|
+
} finally {
|
|
42
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Georeference pic source: `{"geojson": FeatureCollection, "warnings":
|
|
48
|
+
* [...], "diagnostics": [...], "registration": {...}, "canvas": {"rescale",
|
|
49
|
+
* "scale"}}`, or
|
|
50
|
+
* `{"error", "error_info"}` on a pic error, or `{"error", "geo_error":
|
|
51
|
+
* {kind, message, hint}}` on a georeferencing error (bad options included).
|
|
52
|
+
*
|
|
53
|
+
* `opts_json` is a JSON object (or empty string) with the optional keys
|
|
54
|
+
* `frame` (`"enu"` | `"mercator"`), `anchor` (`[lon, lat]`), `scale`
|
|
55
|
+
* (metres per inch), `bearing` (degrees clockwise from north), `features`
|
|
56
|
+
* (`[{name, lon, lat, bbox?}]`, control points by label), `flatten`
|
|
57
|
+
* (inches), `view_scale` (px per inch under `geo_px = 1`) and
|
|
58
|
+
* `screen_classes`. Each overrides the corresponding `geo_*` variable of
|
|
59
|
+
* the source. Animations cannot ride into GeoJSON: a source with `animate`
|
|
60
|
+
* statements adds an `ignored` warning.
|
|
61
|
+
* @param {string} src
|
|
62
|
+
* @param {boolean} circuits
|
|
63
|
+
* @param {boolean} texlabels
|
|
64
|
+
* @param {string} opts_json
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
export function compile_geo(src, circuits, texlabels, opts_json) {
|
|
68
|
+
let deferred3_0;
|
|
69
|
+
let deferred3_1;
|
|
70
|
+
try {
|
|
71
|
+
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
72
|
+
const len0 = WASM_VECTOR_LEN;
|
|
73
|
+
const ptr1 = passStringToWasm0(opts_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
74
|
+
const len1 = WASM_VECTOR_LEN;
|
|
75
|
+
const ret = wasm.compile_geo(ptr0, len0, circuits, texlabels, ptr1, len1);
|
|
76
|
+
deferred3_0 = ret[0];
|
|
77
|
+
deferred3_1 = ret[1];
|
|
78
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
79
|
+
} finally {
|
|
80
|
+
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Like [`compile_with`], but the bundle also carries the device-independent
|
|
86
|
+
* `scene` draw list (docs/scene.md); `flatten` (inches) delivers curves as
|
|
87
|
+
* polylines. The plain entry points above stay byte-identical — the scene is
|
|
88
|
+
* computed only here.
|
|
89
|
+
* @param {string} src
|
|
90
|
+
* @param {boolean} circuits
|
|
91
|
+
* @param {boolean} texlabels
|
|
92
|
+
* @param {number | null | undefined} flatten
|
|
93
|
+
* @param {boolean} outline
|
|
94
|
+
* @returns {string}
|
|
95
|
+
*/
|
|
96
|
+
export function compile_scene(src, circuits, texlabels, flatten, outline) {
|
|
97
|
+
let deferred2_0;
|
|
98
|
+
let deferred2_1;
|
|
99
|
+
try {
|
|
100
|
+
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
101
|
+
const len0 = WASM_VECTOR_LEN;
|
|
102
|
+
const ret = wasm.compile_scene(ptr0, len0, circuits, texlabels, !isLikeNone(flatten), isLikeNone(flatten) ? 0 : flatten, outline);
|
|
103
|
+
deferred2_0 = ret[0];
|
|
104
|
+
deferred2_1 = ret[1];
|
|
105
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
106
|
+
} finally {
|
|
107
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Like [`compile`], with options: `circuits` loads the circuit-element
|
|
113
|
+
* library; `texlabels` sets `texlabels = 1` so `$…$` labels are typeset as
|
|
114
|
+
* TeX math. Note: the default wasm build ships without the math renderer
|
|
115
|
+
* (size budget), so with `texlabels` the labels fall back to literal text
|
|
116
|
+
* and a diagnostic — use the math-enabled build (`--features math`, the
|
|
117
|
+
* `rpic_wasm_math` npm artifact) to typeset them.
|
|
118
|
+
* @param {string} src
|
|
119
|
+
* @param {boolean} circuits
|
|
120
|
+
* @param {boolean} texlabels
|
|
121
|
+
* @returns {string}
|
|
122
|
+
*/
|
|
123
|
+
export function compile_with(src, circuits, texlabels) {
|
|
124
|
+
let deferred2_0;
|
|
125
|
+
let deferred2_1;
|
|
126
|
+
try {
|
|
127
|
+
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
128
|
+
const len0 = WASM_VECTOR_LEN;
|
|
129
|
+
const ret = wasm.compile_with(ptr0, len0, circuits, texlabels);
|
|
130
|
+
deferred2_0 = ret[0];
|
|
131
|
+
deferred2_1 = ret[1];
|
|
132
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
133
|
+
} finally {
|
|
134
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Canvas positions (inches) of WGS84 points under a registration (as
|
|
140
|
+
* `compile_geo` returned it): `points_json` is `[[lon, lat], …]`; returns
|
|
141
|
+
* `[[x, y], …]`, or `{"error", "geo_error"}` when either input does not
|
|
142
|
+
* parse. The host uses it to place features before compiling (two-pass
|
|
143
|
+
* feature injection, see `bindings/js/index.js`).
|
|
144
|
+
* @param {string} registration_json
|
|
145
|
+
* @param {string} points_json
|
|
146
|
+
* @returns {string}
|
|
147
|
+
*/
|
|
148
|
+
export function geo_to_canvas(registration_json, points_json) {
|
|
149
|
+
let deferred3_0;
|
|
150
|
+
let deferred3_1;
|
|
151
|
+
try {
|
|
152
|
+
const ptr0 = passStringToWasm0(registration_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
153
|
+
const len0 = WASM_VECTOR_LEN;
|
|
154
|
+
const ptr1 = passStringToWasm0(points_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
155
|
+
const len1 = WASM_VECTOR_LEN;
|
|
156
|
+
const ret = wasm.geo_to_canvas(ptr0, len0, ptr1, len1);
|
|
157
|
+
deferred3_0 = ret[0];
|
|
158
|
+
deferred3_1 = ret[1];
|
|
159
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
160
|
+
} finally {
|
|
161
|
+
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function __wbg_get_imports() {
|
|
165
|
+
const import0 = {
|
|
166
|
+
__proto__: null,
|
|
167
|
+
__wbindgen_init_externref_table: function() {
|
|
168
|
+
const table = wasm.__wbindgen_externrefs;
|
|
169
|
+
const offset = table.grow(4);
|
|
170
|
+
table.set(0, undefined);
|
|
171
|
+
table.set(offset + 0, undefined);
|
|
172
|
+
table.set(offset + 1, null);
|
|
173
|
+
table.set(offset + 2, true);
|
|
174
|
+
table.set(offset + 3, false);
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
return {
|
|
178
|
+
__proto__: null,
|
|
179
|
+
"./rpic_wasm_geo_bg.js": import0,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function getStringFromWasm0(ptr, len) {
|
|
184
|
+
return decodeText(ptr >>> 0, len);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
let cachedUint8ArrayMemory0 = null;
|
|
188
|
+
function getUint8ArrayMemory0() {
|
|
189
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
190
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
191
|
+
}
|
|
192
|
+
return cachedUint8ArrayMemory0;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function isLikeNone(x) {
|
|
196
|
+
return x === undefined || x === null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
200
|
+
if (realloc === undefined) {
|
|
201
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
202
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
203
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
204
|
+
WASM_VECTOR_LEN = buf.length;
|
|
205
|
+
return ptr;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
let len = arg.length;
|
|
209
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
210
|
+
|
|
211
|
+
const mem = getUint8ArrayMemory0();
|
|
212
|
+
|
|
213
|
+
let offset = 0;
|
|
214
|
+
|
|
215
|
+
for (; offset < len; offset++) {
|
|
216
|
+
const code = arg.charCodeAt(offset);
|
|
217
|
+
if (code > 0x7F) break;
|
|
218
|
+
mem[ptr + offset] = code;
|
|
219
|
+
}
|
|
220
|
+
if (offset !== len) {
|
|
221
|
+
if (offset !== 0) {
|
|
222
|
+
arg = arg.slice(offset);
|
|
223
|
+
}
|
|
224
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
225
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
226
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
227
|
+
|
|
228
|
+
offset += ret.written;
|
|
229
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
WASM_VECTOR_LEN = offset;
|
|
233
|
+
return ptr;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
237
|
+
cachedTextDecoder.decode();
|
|
238
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
239
|
+
let numBytesDecoded = 0;
|
|
240
|
+
function decodeText(ptr, len) {
|
|
241
|
+
numBytesDecoded += len;
|
|
242
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
243
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
244
|
+
cachedTextDecoder.decode();
|
|
245
|
+
numBytesDecoded = len;
|
|
246
|
+
}
|
|
247
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const cachedTextEncoder = new TextEncoder();
|
|
251
|
+
|
|
252
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
253
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
254
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
255
|
+
view.set(buf);
|
|
256
|
+
return {
|
|
257
|
+
read: arg.length,
|
|
258
|
+
written: buf.length
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
let WASM_VECTOR_LEN = 0;
|
|
264
|
+
|
|
265
|
+
let wasmModule, wasmInstance, wasm;
|
|
266
|
+
function __wbg_finalize_init(instance, module) {
|
|
267
|
+
wasmInstance = instance;
|
|
268
|
+
wasm = instance.exports;
|
|
269
|
+
wasmModule = module;
|
|
270
|
+
cachedUint8ArrayMemory0 = null;
|
|
271
|
+
wasm.__wbindgen_start();
|
|
272
|
+
return wasm;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function __wbg_load(module, imports) {
|
|
276
|
+
if (typeof Response === 'function' && module instanceof Response) {
|
|
277
|
+
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
278
|
+
try {
|
|
279
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
const validResponse = module.ok && expectedResponseType(module.type);
|
|
282
|
+
|
|
283
|
+
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
|
284
|
+
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
|
285
|
+
|
|
286
|
+
} else { throw e; }
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const bytes = await module.arrayBuffer();
|
|
291
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
292
|
+
} else {
|
|
293
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
294
|
+
|
|
295
|
+
if (instance instanceof WebAssembly.Instance) {
|
|
296
|
+
return { instance, module };
|
|
297
|
+
} else {
|
|
298
|
+
return instance;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function expectedResponseType(type) {
|
|
303
|
+
switch (type) {
|
|
304
|
+
case 'basic': case 'cors': case 'default': return true;
|
|
305
|
+
}
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function initSync(module) {
|
|
311
|
+
if (wasm !== undefined) return wasm;
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
if (module !== undefined) {
|
|
315
|
+
if (Object.getPrototypeOf(module) === Object.prototype) {
|
|
316
|
+
({module} = module)
|
|
317
|
+
} else {
|
|
318
|
+
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const imports = __wbg_get_imports();
|
|
323
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
324
|
+
module = new WebAssembly.Module(module);
|
|
325
|
+
}
|
|
326
|
+
const instance = new WebAssembly.Instance(module, imports);
|
|
327
|
+
return __wbg_finalize_init(instance, module);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function __wbg_init(module_or_path) {
|
|
331
|
+
if (wasm !== undefined) return wasm;
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
if (module_or_path !== undefined) {
|
|
335
|
+
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
|
336
|
+
({module_or_path} = module_or_path)
|
|
337
|
+
} else {
|
|
338
|
+
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (module_or_path === undefined) {
|
|
343
|
+
module_or_path = new URL('rpic_wasm_geo_bg.wasm', import.meta.url);
|
|
344
|
+
}
|
|
345
|
+
const imports = __wbg_get_imports();
|
|
346
|
+
|
|
347
|
+
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
|
348
|
+
module_or_path = fetch(module_or_path);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
|
352
|
+
|
|
353
|
+
return __wbg_finalize_init(instance, module);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export { initSync, __wbg_init as default };
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const compile_geo: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
5
|
+
export const geo_to_canvas: (a: number, b: number, c: number, d: number) => [number, number];
|
|
6
|
+
export const compile: (a: number, b: number) => [number, number];
|
|
7
|
+
export const compile_circuits: (a: number, b: number) => [number, number];
|
|
8
|
+
export const compile_scene: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
9
|
+
export const compile_with: (a: number, b: number, c: number, d: number) => [number, number];
|
|
10
|
+
export const __wbindgen_externrefs: WebAssembly.Table;
|
|
11
|
+
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
12
|
+
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
13
|
+
export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
14
|
+
export const __wbindgen_start: () => void;
|
|
Binary file
|