@danielsimonjr/sciengjs 0.3.2 → 0.5.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 +119 -5
- package/THIRD_PARTY_NOTICES.md +33 -1
- package/dist/browser/page.d.ts +7 -0
- package/dist/browser/page.js +27 -1
- package/dist/browser/page.js.map +1 -1
- package/dist/browser/pinned.d.ts +8 -0
- package/dist/browser/pinned.js +8 -0
- package/dist/browser/pinned.js.map +1 -1
- package/dist/math/backend-pdf.d.ts +3 -0
- package/dist/math/backend-pdf.js +14 -0
- package/dist/math/backend-pdf.js.map +1 -0
- package/dist/math/backend-png.d.ts +3 -0
- package/dist/math/backend-png.js +15 -0
- package/dist/math/backend-png.js.map +1 -0
- package/dist/math/backend-svg.d.ts +3 -0
- package/dist/math/backend-svg.js +12 -0
- package/dist/math/backend-svg.js.map +1 -0
- package/dist/math/font-ranges.d.ts +59 -0
- package/dist/math/font-ranges.js +93 -0
- package/dist/math/font-ranges.js.map +1 -0
- package/dist/math/index.d.ts +3 -0
- package/dist/math/index.js +3 -0
- package/dist/math/index.js.map +1 -0
- package/dist/math/tex.d.ts +39 -0
- package/dist/math/tex.js +130 -0
- package/dist/math/tex.js.map +1 -0
- package/dist/plot/backend-html.d.ts +3 -0
- package/dist/plot/backend-html.js +13 -0
- package/dist/plot/backend-html.js.map +1 -0
- package/dist/plot/backend-png.d.ts +3 -0
- package/dist/plot/backend-png.js +12 -0
- package/dist/plot/backend-png.js.map +1 -0
- package/dist/plot/backend-svg.d.ts +7 -0
- package/dist/plot/backend-svg.js +21 -0
- package/dist/plot/backend-svg.js.map +1 -0
- package/dist/plot/control.d.ts +93 -0
- package/dist/plot/control.js +811 -0
- package/dist/plot/control.js.map +1 -0
- package/dist/plot/index.d.ts +6 -0
- package/dist/plot/index.js +6 -0
- package/dist/plot/index.js.map +1 -0
- package/dist/plot/plotter.d.ts +7 -0
- package/dist/plot/plotter.js +491 -0
- package/dist/plot/plotter.js.map +1 -0
- package/dist/plot/reader.d.ts +10 -0
- package/dist/plot/reader.js +266 -0
- package/dist/plot/reader.js.map +1 -0
- package/dist/plot/ticks.d.ts +13 -0
- package/dist/plot/ticks.js +67 -0
- package/dist/plot/ticks.js.map +1 -0
- package/dist/registry.js +6 -0
- package/dist/registry.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +12 -2
package/dist/math/tex.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { liteAdaptor } from "@mathjax/src/js/adaptors/liteAdaptor.js";
|
|
2
|
+
import { RegisterHTMLHandler } from "@mathjax/src/js/handlers/html.js";
|
|
3
|
+
import { mathjax } from "@mathjax/src/js/mathjax.js";
|
|
4
|
+
import { TeX } from "@mathjax/src/js/input/tex.js";
|
|
5
|
+
import { SVG } from "@mathjax/src/js/output/svg.js";
|
|
6
|
+
import "@mathjax/src/js/input/tex/base/BaseConfiguration.js";
|
|
7
|
+
import "@mathjax/src/js/input/tex/ams/AmsConfiguration.js";
|
|
8
|
+
import "@mathjax/src/js/input/tex/boldsymbol/BoldsymbolConfiguration.js";
|
|
9
|
+
import "@mathjax/src/js/input/tex/color/ColorConfiguration.js";
|
|
10
|
+
import "@mathjax/src/js/input/tex/mhchem/MhchemConfiguration.js";
|
|
11
|
+
import { RenderError } from "../errors.js";
|
|
12
|
+
import { defineMhchemVariant, loadFontRanges } from "./font-ranges.js";
|
|
13
|
+
/** The TeX packages that this build holds. Each one is imported above; no other package loads. */
|
|
14
|
+
export const MATH_PACKAGES = ["base", "ams", "boldsymbol", "color", "mhchem"];
|
|
15
|
+
/** Pixels per MathJax ex unit. MathJax reports sizes in ex; the SVG attributes state pixels. */
|
|
16
|
+
const EX_PX = 8;
|
|
17
|
+
/** Matches one `\require{...}` command and captures its package list. */
|
|
18
|
+
const REQUIRE = /\\require\s*\{([^}]*)\}/g;
|
|
19
|
+
/**
|
|
20
|
+
* Removes each `\require{...}` command from the source and returns the rest. The build loads every
|
|
21
|
+
* held package before the render and holds no require package, so a `\require` of held packages is a
|
|
22
|
+
* no-op. A `\require` of a package that this build does not hold rejects with E_UNSUPPORTED and names
|
|
23
|
+
* the package. MathJax never fetches a package.
|
|
24
|
+
*/
|
|
25
|
+
export function stripRequires(source) {
|
|
26
|
+
for (const match of source.matchAll(REQUIRE)) {
|
|
27
|
+
for (const raw of match[1].split(",")) {
|
|
28
|
+
const name = raw.trim();
|
|
29
|
+
if (name !== "" && !MATH_PACKAGES.includes(name)) {
|
|
30
|
+
throw new RenderError("E_UNSUPPORTED", `the math stage does not hold the package ${name}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return source.replace(REQUIRE, "");
|
|
35
|
+
}
|
|
36
|
+
/** The five named XML entities, by name. */
|
|
37
|
+
const XML_ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
|
|
38
|
+
/** Decodes the numeric and the five named XML entities of a text. */
|
|
39
|
+
function decodeXml(text) {
|
|
40
|
+
return text.replace(/&(?:#x([0-9A-Fa-f]+)|#(\d+)|(amp|lt|gt|quot|apos));/g, (whole, hex, dec, name) => {
|
|
41
|
+
if (hex !== undefined)
|
|
42
|
+
return String.fromCodePoint(parseInt(hex, 16));
|
|
43
|
+
if (dec !== undefined)
|
|
44
|
+
return String.fromCodePoint(parseInt(dec, 10));
|
|
45
|
+
return XML_ENTITIES[name] ?? whole;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Rejects an SVG that draws a character as system-font text. MathJax writes a `<text>` element with a
|
|
50
|
+
* `font-family` when the math font holds no glyph for a character. Such output depends on the fonts of
|
|
51
|
+
* the viewer, and the PNG stage has no font. The error names each such character and its code point.
|
|
52
|
+
*/
|
|
53
|
+
export function rejectFontFallback(svg) {
|
|
54
|
+
if (!svg.includes("<text") && !svg.includes("font-family"))
|
|
55
|
+
return;
|
|
56
|
+
const chars = new Set();
|
|
57
|
+
for (const match of svg.matchAll(/<text\b[^>]*>([^<]*)<\/text>/g)) {
|
|
58
|
+
for (const ch of decodeXml(match[1]))
|
|
59
|
+
chars.add(ch);
|
|
60
|
+
}
|
|
61
|
+
if (chars.size === 0) {
|
|
62
|
+
throw new RenderError("E_UNSUPPORTED", "the math svg uses a system font");
|
|
63
|
+
}
|
|
64
|
+
const names = [...chars].map((ch) => `${ch} (U+${ch.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")})`);
|
|
65
|
+
throw new RenderError("E_UNSUPPORTED", `the math font holds no glyph for ${names.join(", ")}`);
|
|
66
|
+
}
|
|
67
|
+
/** Converts a MathJax size string such as "2.5ex" to pixels, rounded to 3 decimals. */
|
|
68
|
+
export function exToPx(value) {
|
|
69
|
+
const match = /^(-?[\d.]+)ex$/.exec(value);
|
|
70
|
+
if (match === null) {
|
|
71
|
+
throw new RenderError("E_INTERNAL", `unexpected MathJax size: ${value}`);
|
|
72
|
+
}
|
|
73
|
+
return String(Math.round(Number(match[1]) * EX_PX * 1000) / 1000);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Keeps the `<svg>` element of a MathJax container and sets the standalone attributes:
|
|
77
|
+
* the SVG namespace, the sizes in px and the viewBox. Only the SVG element leaves this function,
|
|
78
|
+
* so the assistive MathML of the container is removed.
|
|
79
|
+
*/
|
|
80
|
+
export function standaloneSvg(container) {
|
|
81
|
+
const start = container.indexOf("<svg");
|
|
82
|
+
const end = container.lastIndexOf("</svg>");
|
|
83
|
+
if (start === -1 || end === -1) {
|
|
84
|
+
throw new RenderError("E_INTERNAL", "MathJax produced no svg element");
|
|
85
|
+
}
|
|
86
|
+
const element = container.slice(start, end + "</svg>".length);
|
|
87
|
+
const open = /^<svg([^>]*)>/.exec(element);
|
|
88
|
+
if (open === null) {
|
|
89
|
+
throw new RenderError("E_INTERNAL", "MathJax produced a malformed svg element");
|
|
90
|
+
}
|
|
91
|
+
const attrs = open[1];
|
|
92
|
+
const width = /\swidth="([^"]+)"/.exec(attrs)?.[1];
|
|
93
|
+
const height = /\sheight="([^"]+)"/.exec(attrs)?.[1];
|
|
94
|
+
const viewBox = /\sviewBox="([^"]+)"/.exec(attrs)?.[1];
|
|
95
|
+
if (width === undefined || height === undefined || viewBox === undefined) {
|
|
96
|
+
throw new RenderError("E_INTERNAL", "MathJax svg has no width, height or viewBox");
|
|
97
|
+
}
|
|
98
|
+
const head = `<svg xmlns="http://www.w3.org/2000/svg" width="${exToPx(width)}px" height="${exToPx(height)}px" viewBox="${viewBox}"`;
|
|
99
|
+
return head + element.slice(open[0].length - 1);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Renders LaTeX math to a standalone SVG with the glyphs as paths. The XML serializer escapes `<`, `>`,
|
|
103
|
+
* `&` and `"` in the attribute values, so the TeX source in the data-latex attributes keeps the SVG
|
|
104
|
+
* well-formed. Rejects with E_INPUT or E_UNSUPPORTED.
|
|
105
|
+
*/
|
|
106
|
+
export async function mathToSvg(source, options) {
|
|
107
|
+
const tex = stripRequires(source);
|
|
108
|
+
const adaptor = liteAdaptor();
|
|
109
|
+
RegisterHTMLHandler(adaptor);
|
|
110
|
+
let inputError;
|
|
111
|
+
const input = new TeX({
|
|
112
|
+
packages: [...MATH_PACKAGES],
|
|
113
|
+
formatError: (jax, err) => {
|
|
114
|
+
inputError ??= err.message;
|
|
115
|
+
return jax.formatError(err);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const output = new SVG({ fontCache: "none" });
|
|
119
|
+
loadFontRanges(output.font);
|
|
120
|
+
defineMhchemVariant(output.font);
|
|
121
|
+
const doc = mathjax.document("", { InputJax: input, OutputJax: output });
|
|
122
|
+
const node = doc.convert(tex, { display: options.display });
|
|
123
|
+
if (inputError !== undefined) {
|
|
124
|
+
throw new RenderError("E_INPUT", `TeX input error: ${inputError}`);
|
|
125
|
+
}
|
|
126
|
+
const svg = standaloneSvg(adaptor.serializeXML(node));
|
|
127
|
+
rejectFontFallback(svg);
|
|
128
|
+
return svg;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=tex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tex.js","sourceRoot":"","sources":["../../src/math/tex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BackendOutput, WorkerJob } from "../worker/protocol.ts";
|
|
2
|
+
/** Renders plot to html: one standalone page that loads the pinned Plotly build and draws the figure. The page title is the figure title, or "plot". */
|
|
3
|
+
export declare function render(request: WorkerJob["request"]): Promise<BackendOutput>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { plotlyPageHtml } from "../browser/page.js";
|
|
2
|
+
import { PLOTLY_CDN_URL, PLOTLY_SRI } from "../browser/pinned.js";
|
|
3
|
+
import { readPlotOptions } from "./backend-svg.js";
|
|
4
|
+
import { readPlotFigure } from "./reader.js";
|
|
5
|
+
/** Renders plot to html: one standalone page that loads the pinned Plotly build and draws the figure. The page title is the figure title, or "plot". */
|
|
6
|
+
export async function render(request) {
|
|
7
|
+
const { lenient } = readPlotOptions(request.options, ["lenient"]);
|
|
8
|
+
const { figure, warnings } = readPlotFigure(String(request.source), { lenient });
|
|
9
|
+
const title = figure.layout.title?.text;
|
|
10
|
+
const html = plotlyPageHtml(figure, PLOTLY_CDN_URL, PLOTLY_SRI, typeof title === "string" && title !== "" ? title : "plot");
|
|
11
|
+
return { bytes: new TextEncoder().encode(html), warnings };
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=backend-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-html.js","sourceRoot":"","sources":["../../src/plot/backend-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,wJAAwJ;AACxJ,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAA6B;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAClE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACjF,MAAM,KAAK,GAAI,MAAM,CAAC,MAAM,CAAC,KAAwC,EAAE,IAAI,CAAC;IAC5E,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5H,OAAO,EAAE,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { readScale, svgDocumentToPng } from "../graph/backend-png.js";
|
|
2
|
+
import { plotToSvg } from "./plotter.js";
|
|
3
|
+
import { readPlotOptions } from "./backend-svg.js";
|
|
4
|
+
/** Renders plot to png: the SVG of the figure, then the PNG of that SVG at the option scale. */
|
|
5
|
+
export async function render(request) {
|
|
6
|
+
const { lenient } = readPlotOptions(request.options, ["lenient", "scale"]);
|
|
7
|
+
const scale = readScale(request.options);
|
|
8
|
+
const result = plotToSvg(String(request.source), { lenient });
|
|
9
|
+
const png = await svgDocumentToPng(result.svg, request, scale);
|
|
10
|
+
return { bytes: png.bytes, warnings: [...result.warnings, ...(png.warnings ?? [])] };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=backend-png.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-png.js","sourceRoot":"","sources":["../../src/plot/backend-png.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAA6B;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/D,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;AACvF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BackendOutput, WorkerJob } from "../worker/protocol.ts";
|
|
2
|
+
/** Reads the plot options. The only key is lenient, a boolean. Any other key rejects with E_INPUT. */
|
|
3
|
+
export declare function readPlotOptions(options: Record<string, unknown>, allowed: readonly string[]): {
|
|
4
|
+
lenient: boolean;
|
|
5
|
+
};
|
|
6
|
+
/** Renders plot to svg. The options are lenient only. */
|
|
7
|
+
export declare function render(request: WorkerJob["request"]): Promise<BackendOutput>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RenderError } from "../errors.js";
|
|
2
|
+
import { plotToSvg } from "./plotter.js";
|
|
3
|
+
/** Reads the plot options. The only key is lenient, a boolean. Any other key rejects with E_INPUT. */
|
|
4
|
+
export function readPlotOptions(options, allowed) {
|
|
5
|
+
for (const key of Object.keys(options)) {
|
|
6
|
+
if (!allowed.includes(key))
|
|
7
|
+
throw new RenderError("E_INPUT", "plot takes no option " + key);
|
|
8
|
+
}
|
|
9
|
+
const lenient = options.lenient;
|
|
10
|
+
if (lenient !== undefined && typeof lenient !== "boolean") {
|
|
11
|
+
throw new RenderError("E_INPUT", "option lenient must be true or false");
|
|
12
|
+
}
|
|
13
|
+
return { lenient: lenient === true };
|
|
14
|
+
}
|
|
15
|
+
/** Renders plot to svg. The options are lenient only. */
|
|
16
|
+
export async function render(request) {
|
|
17
|
+
const { lenient } = readPlotOptions(request.options, ["lenient"]);
|
|
18
|
+
const result = plotToSvg(String(request.source), { lenient });
|
|
19
|
+
return { bytes: new TextEncoder().encode(result.svg), warnings: result.warnings };
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=backend-svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-svg.js","sourceRoot":"","sources":["../../src/plot/backend-svg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,sGAAsG;AACtG,MAAM,UAAU,eAAe,CAAC,OAAgC,EAAE,OAA0B;IAC1F,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,uBAAuB,GAAG,GAAG,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1D,MAAM,IAAI,WAAW,CAAC,SAAS,EAAE,sCAAsC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAA6B;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,OAAO,EAAE,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** A transfer function G(s) = num(s) / den(s). Coefficients are in descending powers of s. */
|
|
2
|
+
export interface TransferFunction {
|
|
3
|
+
num: number[];
|
|
4
|
+
den: number[];
|
|
5
|
+
}
|
|
6
|
+
/** A complex number. */
|
|
7
|
+
export interface Complex {
|
|
8
|
+
re: number;
|
|
9
|
+
im: number;
|
|
10
|
+
}
|
|
11
|
+
/** The Plotly subset that the plotter reads. */
|
|
12
|
+
export interface ControlFigure {
|
|
13
|
+
data: Array<Record<string, unknown>>;
|
|
14
|
+
layout: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/** A figure plus the numbers that the analysis derived from the same model. */
|
|
17
|
+
export interface ControlResult<N> {
|
|
18
|
+
figure: ControlFigure;
|
|
19
|
+
numbers: N;
|
|
20
|
+
}
|
|
21
|
+
/** Options for the frequency helpers: the grid from wMin to wMax, in rad/s, with points samples. */
|
|
22
|
+
export interface FrequencyOptions {
|
|
23
|
+
wMin?: number;
|
|
24
|
+
wMax?: number;
|
|
25
|
+
points?: number;
|
|
26
|
+
}
|
|
27
|
+
/** Options for the time helpers: the end time tEnd and the number of points. */
|
|
28
|
+
export interface TimeOptions {
|
|
29
|
+
tEnd?: number;
|
|
30
|
+
points?: number;
|
|
31
|
+
}
|
|
32
|
+
/** Options for rootLocus: the largest gain kMax and the number of points. */
|
|
33
|
+
export interface RootLocusOptions {
|
|
34
|
+
kMax?: number;
|
|
35
|
+
points?: number;
|
|
36
|
+
}
|
|
37
|
+
/** Key values of a Bode plot: crossover frequencies in rad/s, margins in degrees. A null value means none was found. */
|
|
38
|
+
export interface BodeNumbers {
|
|
39
|
+
gainCrossover: number | null;
|
|
40
|
+
phaseCrossover: number | null;
|
|
41
|
+
gainMargin: number | null;
|
|
42
|
+
phaseMargin: number | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Key values of a step response: final value, rise and settling times, overshoot in percent, and peak time.
|
|
46
|
+
* The peak and the overshoot are measured in the direction of the final value. A system with a pole on or
|
|
47
|
+
* right of the imaginary axis has no final value, so every number is null. A response with no peak before
|
|
48
|
+
* the end of the time grid has a null peak time and an overshoot of 0.
|
|
49
|
+
*/
|
|
50
|
+
export interface StepNumbers {
|
|
51
|
+
finalValue: number | null;
|
|
52
|
+
riseTime: number | null;
|
|
53
|
+
settlingTime: number | null;
|
|
54
|
+
overshoot: number | null;
|
|
55
|
+
peakTime: number | null;
|
|
56
|
+
}
|
|
57
|
+
/** Key values of an impulse response: the peak value and the time of the peak. */
|
|
58
|
+
export interface ImpulseNumbers {
|
|
59
|
+
peak: number;
|
|
60
|
+
peakTime: number;
|
|
61
|
+
}
|
|
62
|
+
/** The poles and the zeros of a transfer function, as complex numbers. */
|
|
63
|
+
export interface PoleZeroNumbers {
|
|
64
|
+
poles: Complex[];
|
|
65
|
+
zeros: Complex[];
|
|
66
|
+
}
|
|
67
|
+
/** The least distance from the Nyquist curve to the point -1. */
|
|
68
|
+
export interface NyquistNumbers {
|
|
69
|
+
minDistanceToMinusOne: number;
|
|
70
|
+
}
|
|
71
|
+
/** The breakaway points of the root locus, each with its gain k. */
|
|
72
|
+
export interface RootLocusNumbers {
|
|
73
|
+
breakawayPoints: Array<{
|
|
74
|
+
re: number;
|
|
75
|
+
k: number;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
/** Validates a transfer function. Rejects with E_INPUT: empty, non-finite, leading-zero den, or improper. */
|
|
79
|
+
export declare function checkTransferFunction(input: unknown): TransferFunction;
|
|
80
|
+
/** The roots of a polynomial with descending coefficients. Each trailing zero coefficient gives an exact root at 0; Durand-Kerner finds the others. No convergence rejects with E_INPUT. */
|
|
81
|
+
export declare function polynomialRoots(coeffs: number[]): Complex[];
|
|
82
|
+
/** Bode plot. Crossovers and margins are null where no crossing exists. */
|
|
83
|
+
export declare function bode(input: unknown, options?: FrequencyOptions): ControlResult<BodeNumbers>;
|
|
84
|
+
/** Step response by exact zero-order-hold simulation. finalValue is the DC gain, null for a system that is not stable. */
|
|
85
|
+
export declare function step(input: unknown, options?: TimeOptions): ControlResult<StepNumbers>;
|
|
86
|
+
/** Impulse response of the strictly proper part, C e^(At) B for t > 0. A direct feedthrough term is not plotted. */
|
|
87
|
+
export declare function impulse(input: unknown, options?: TimeOptions): ControlResult<ImpulseNumbers>;
|
|
88
|
+
/** Pole-zero map: poles as crosses, zeros as circles. */
|
|
89
|
+
export declare function poleZero(input: unknown): ControlResult<PoleZeroNumbers>;
|
|
90
|
+
/** Nyquist plot of G(j omega) for negative and positive frequencies, with the critical point -1. */
|
|
91
|
+
export declare function nyquist(input: unknown, options?: FrequencyOptions): ControlResult<NyquistNumbers>;
|
|
92
|
+
/** Root locus of den + K num = 0 for K from 0 to kMax, with breakaway points on the real axis. */
|
|
93
|
+
export declare function rootLocus(input: unknown, options?: RootLocusOptions): ControlResult<RootLocusNumbers>;
|