packages/core/src/features/textures/lib/electric-sources.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import type { TendrilsMessage, TendrilsOptions } from './tendrils.js';
2 import { point, range, type ElectricPoint } from "./electric-shared.js";
3
4 /**
5 * A weighted attachment site in normalized texture coordinates.
6 *
7 * @see {@link ElectricPoint}
8 * @see {@link ElectricSourceMessage}
9 * @see {@link TendrilsOptions}
10 */
11 export interface ElectricSource {
12 /** Stable identifier of this resource or connection. See {@link ElectricSource}. */
13 readonly id: string;
14 /** A point in the operation's coordinate system. See {@link ElectricPoint}. */
15 readonly point: ElectricPoint;
16 /** Relative sampling weight or source intensity. See {@link ElectricSource}. */
17 readonly weight: number;
18 }
19 /**
20 * Upserts, removes, or replaces the named source electrodes of an electrical texture.
21 *
22 * @see {@link ElectricSource}
23 * @see {@link TendrilsMessage}
24 */
25 export type ElectricSourceMessage =
26 | {
27 /** The literal "upsert-source" identifying this variant. See {@link ElectricSourceMessage}. */
28 readonly type: "upsert-source";
29 /** Named electrode to insert or replace. See {@link ElectricSource}. */
30 readonly source: ElectricSource;
31 }
32 | {
33 /** The literal "remove-source" identifying this variant. See {@link ElectricSourceMessage}. */
34 readonly type: "remove-source";
35 /** Stable identifier of this resource or connection. See {@link ElectricSourceMessage}. */
36 readonly id: string;
37 }
38 | {
39 /** The literal "set-sources" identifying this variant. See {@link ElectricSourceMessage}. */
40 readonly type: "set-sources";
41 /** Named electrical source electrodes. See {@link ElectricSource}. */
42 readonly sources: readonly ElectricSource[];
43 };
44
45 export const MAX_ELECTRIC_SOURCES = 512;
46 export function sourceId(id: string): string {
47 if (typeof id !== "string" || id.length < 1 || id.length > 128)
48 throw new RangeError("Electric source id must contain 1..128 characters.");
49 return id;
50 }
51 export function source(value: ElectricSource): ElectricSource {
52 return {
53 id: sourceId(value.id),
54 point: point(value.point),
55 weight: range(value.weight, 0, 1_000_000, "Source weight"),
56 };
57 }
58 export function sources(values: readonly ElectricSource[]): ElectricSource[] {
59 if (!Array.isArray(values) || values.length > MAX_ELECTRIC_SOURCES)
60 throw new RangeError(
61 "Electric sources must be an array of at most 512 sites.",
62 );
63 const ids = new Set<string>();
64 const result = values.map((value) => {
65 const next = source(value);
66 if (ids.has(next.id))
67 throw new TypeError(`Duplicate electric source id: ${next.id}`);
68 ids.add(next.id);
69 return next;
70 });
71 return result.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
72 }
73 export interface SourceSite {
74 id: string;
75 point: ElectricPoint;
76 weight: number;
77 hash: number;
78 }
79 export function site(value: ElectricSource): SourceSite {
80 let hash = 2166136261;
81 for (let i = 0; i < value.id.length; i++)
82 hash = Math.imul(hash ^ value.id.charCodeAt(i), 16777619);
83 return { ...value, point: { ...value.point }, hash };
84 }
85
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.