Skip to content

packages/core/src/features/textures/lib/electric-sources.ts

Read as Markdown

This is the source snapshot used to build these API details. View this revision on GitHub.

Back to reference

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 built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.