smithkit 0.1.1 → 0.3.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 +291 -42
- package/dist/lib/MarkerMeasurements.d.ts +6 -0
- package/dist/lib/MarkerMeasurements.js +22 -0
- package/dist/lib/Smith.d.ts +18 -35
- package/dist/lib/Smith.js +107 -275
- package/dist/lib/SmithFormatter.d.ts +10 -0
- package/dist/lib/SmithFormatter.js +19 -0
- package/dist/lib/appearance/SvgTheme.d.ts +6 -0
- package/dist/lib/appearance/SvgTheme.js +21 -0
- package/dist/lib/appearance/Theme.d.ts +8 -0
- package/dist/lib/appearance/Theme.js +120 -0
- package/dist/lib/appearance/types.d.ts +55 -0
- package/dist/lib/grid/CircleLayerControl.d.ts +15 -0
- package/dist/lib/grid/CircleLayerControl.js +40 -0
- package/dist/lib/{draw → grid}/ConstCircles.d.ts +4 -9
- package/dist/lib/{draw → grid}/ConstCircles.js +8 -22
- package/dist/lib/{draw → grid}/ConstQCircles.d.ts +2 -2
- package/dist/lib/{draw → grid}/ConstQCircles.js +4 -4
- package/dist/lib/{draw → grid}/ConstSwrCircles.d.ts +2 -2
- package/dist/lib/{draw → grid}/ConstSwrCircles.js +4 -4
- package/dist/lib/grid/GridDefinitions.d.ts +18 -0
- package/dist/lib/grid/GridDefinitions.js +167 -0
- package/dist/lib/grid/GridGeometry.d.ts +26 -0
- package/dist/lib/grid/GridGeometry.js +58 -0
- package/dist/lib/grid/GridLabels.d.ts +8 -0
- package/dist/lib/grid/GridLabels.js +45 -0
- package/dist/lib/grid/GridLayerControl.d.ts +13 -0
- package/dist/lib/grid/GridLayerControl.js +48 -0
- package/dist/lib/grid/LayerControl.d.ts +6 -0
- package/dist/lib/grid/LayerControl.js +16 -0
- package/dist/lib/grid/SmithGridLayer.d.ts +26 -0
- package/dist/lib/grid/SmithGridLayer.js +95 -0
- package/dist/lib/grid/types.d.ts +1 -1
- package/dist/lib/index.d.ts +11 -11
- package/dist/lib/index.js +5 -7
- package/dist/lib/{draw → interaction}/SmithCursor.d.ts +3 -20
- package/dist/lib/{draw → interaction}/SmithCursor.js +12 -20
- package/dist/lib/io/Touchstone.d.ts +10 -0
- package/dist/lib/io/Touchstone.js +75 -0
- package/dist/lib/layers.d.ts +7 -9
- package/dist/lib/layers.js +1 -73
- package/dist/lib/{complex → math}/Complex.d.ts +1 -0
- package/dist/lib/{complex → math}/Complex.js +1 -1
- package/dist/lib/math/geometry.d.ts +14 -0
- package/dist/lib/measurements.d.ts +2 -4
- package/dist/lib/measurements.js +1 -19
- package/dist/lib/rendering/SvgChartRenderer.d.ts +66 -0
- package/dist/lib/rendering/SvgChartRenderer.js +342 -0
- package/dist/lib/rf/RfCalculations.d.ts +65 -0
- package/dist/lib/rf/RfCalculations.js +161 -0
- package/dist/lib/{SmithConstantCircle.d.ts → rf/SmithConstantCircle.d.ts} +2 -3
- package/dist/lib/{SmithConstantCircle.js → rf/SmithConstantCircle.js} +3 -4
- package/dist/lib/scales/PeripheralScaleDefinitions.d.ts +16 -0
- package/dist/lib/scales/PeripheralScaleDefinitions.js +54 -0
- package/dist/lib/scales/RadialScaleDefinitions.d.ts +15 -0
- package/dist/lib/scales/RadialScaleDefinitions.js +112 -0
- package/dist/lib/scales/SmithPeripheralScales.d.ts +4 -2
- package/dist/lib/scales/SmithPeripheralScales.js +55 -35
- package/dist/lib/scales/SmithScales.d.ts +11 -2
- package/dist/lib/scales/SmithScales.js +78 -38
- package/dist/lib/svg/ImageExporter.d.ts +18 -0
- package/dist/lib/svg/ImageExporter.js +211 -0
- package/dist/lib/svg/LabelLayout.d.ts +17 -0
- package/dist/lib/svg/LabelLayout.js +145 -0
- package/dist/lib/svg/MarkerLegend.d.ts +12 -0
- package/dist/lib/svg/MarkerLegend.js +63 -0
- package/dist/lib/{draw → svg}/SmithArc.d.ts +1 -1
- package/dist/lib/{draw → svg}/SmithCircle.d.ts +1 -1
- package/dist/lib/{draw → svg}/SmithLine.d.ts +1 -1
- package/dist/lib/{draw → svg}/SmithScaler.d.ts +1 -4
- package/dist/lib/{draw → svg}/SmithText.d.ts +1 -1
- package/dist/lib/svg/SvgExporter.d.ts +19 -0
- package/dist/lib/svg/SvgExporter.js +182 -0
- package/dist/lib/svg/export.d.ts +36 -0
- package/dist/lib/{draw → traces}/SmithData.d.ts +24 -35
- package/dist/lib/traces/SmithData.js +195 -0
- package/dist/lib/{draw → traces}/SmithMarker.d.ts +14 -3
- package/dist/lib/traces/SmithMarker.js +240 -0
- package/dist/lib/traces/TraceModel.d.ts +31 -0
- package/dist/lib/traces/TraceModel.js +123 -0
- package/dist/lib/traces/TraceRenderer.d.ts +33 -0
- package/dist/lib/traces/TraceRenderer.js +152 -0
- package/package.json +4 -1
- package/dist/lib/SmithArcsDefs.d.ts +0 -10
- package/dist/lib/SmithArcsDefs.js +0 -10
- package/dist/lib/components.d.ts +0 -14
- package/dist/lib/components.js +0 -26
- package/dist/lib/draw/SmithData.js +0 -366
- package/dist/lib/draw/SmithGridLayer.d.ts +0 -19
- package/dist/lib/draw/SmithGridLayer.js +0 -48
- package/dist/lib/draw/SmithMarker.js +0 -122
- package/dist/lib/formatting.d.ts +0 -7
- package/dist/lib/formatting.js +0 -16
- package/dist/lib/grid/definitions.d.ts +0 -3
- package/dist/lib/grid/definitions.js +0 -123
- package/dist/lib/grid/geometry.d.ts +0 -20
- package/dist/lib/grid/geometry.js +0 -55
- package/dist/lib/grid/labels.d.ts +0 -3
- package/dist/lib/grid/labels.js +0 -41
- package/dist/lib/io/touchstone.d.ts +0 -7
- package/dist/lib/io/touchstone.js +0 -72
- package/dist/lib/math/complexRatio.d.ts +0 -3
- package/dist/lib/math/complexRatio.js +0 -30
- package/dist/lib/renormalization.d.ts +0 -10
- package/dist/lib/renormalization.js +0 -62
- package/dist/lib/rf.d.ts +0 -35
- package/dist/lib/rf.js +0 -74
- package/dist/lib/scales/peripheralScales.d.ts +0 -12
- package/dist/lib/scales/peripheralScales.js +0 -49
- package/dist/lib/scales/radialScales.d.ts +0 -12
- package/dist/lib/scales/radialScales.js +0 -109
- package/dist/lib/shapes/Arc.d.ts +0 -6
- package/dist/lib/shapes/Circle.d.ts +0 -5
- package/dist/lib/shapes/Line.d.ts +0 -5
- package/dist/lib/shapes/Point.d.ts +0 -1
- package/dist/lib/shapes/Point.js +0 -1
- /package/dist/lib/{draw/SmithDrawOptions.js → appearance/types.js} +0 -0
- /package/dist/lib/{draw → grid}/ConstConductance.d.ts +0 -0
- /package/dist/lib/{draw → grid}/ConstConductance.js +0 -0
- /package/dist/lib/{draw → grid}/ConstReactance.d.ts +0 -0
- /package/dist/lib/{draw → grid}/ConstReactance.js +0 -0
- /package/dist/lib/{draw → grid}/ConstResistance.d.ts +0 -0
- /package/dist/lib/{draw → grid}/ConstResistance.js +0 -0
- /package/dist/lib/{draw → grid}/ConstSusceptance.d.ts +0 -0
- /package/dist/lib/{draw → grid}/ConstSusceptance.js +0 -0
- /package/dist/lib/{arcs → grid}/Tick.d.ts +0 -0
- /package/dist/lib/{arcs → grid}/Tick.js +0 -0
- /package/dist/lib/{draw → interaction}/MouseGesture.d.ts +0 -0
- /package/dist/lib/{draw → interaction}/MouseGesture.js +0 -0
- /package/dist/lib/{shapes/Arc.js → math/geometry.js} +0 -0
- /package/dist/lib/{draw → svg}/SmithArc.js +0 -0
- /package/dist/lib/{draw → svg}/SmithCircle.js +0 -0
- /package/dist/lib/{draw → svg}/SmithDrawOptions.d.ts +0 -0
- /package/dist/lib/{shapes/Circle.js → svg/SmithDrawOptions.js} +0 -0
- /package/dist/lib/{draw → svg}/SmithGroup.d.ts +0 -0
- /package/dist/lib/{draw → svg}/SmithGroup.js +0 -0
- /package/dist/lib/{draw → svg}/SmithLine.js +0 -0
- /package/dist/lib/{draw → svg}/SmithPath.d.ts +0 -0
- /package/dist/lib/{draw → svg}/SmithPath.js +0 -0
- /package/dist/lib/{draw → svg}/SmithScaler.js +0 -0
- /package/dist/lib/{draw → svg}/SmithShape.d.ts +0 -0
- /package/dist/lib/{draw → svg}/SmithShape.js +0 -0
- /package/dist/lib/{draw → svg}/SmithSvg.d.ts +0 -0
- /package/dist/lib/{draw → svg}/SmithSvg.js +0 -0
- /package/dist/lib/{draw → svg}/SmithText.js +0 -0
- /package/dist/lib/{shapes/Line.js → svg/export.js} +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Tick } from './Tick.js';
|
|
2
|
+
export class GridLabels {
|
|
3
|
+
constructor() { }
|
|
4
|
+
static values = [
|
|
5
|
+
0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 3, 4, 5, 10, 20, 50,
|
|
6
|
+
];
|
|
7
|
+
static interiorValues = [0.2, 0.4, 0.6, 0.8, 1];
|
|
8
|
+
static resistance() {
|
|
9
|
+
const axis = [0, ...GridLabels.values].map((r) => new Tick({
|
|
10
|
+
point: { r, i: 0 },
|
|
11
|
+
dp: r === 0 || r >= 10 ? 0 : 1,
|
|
12
|
+
// Keep the zero inside the rim and clear of the opposite grid's high-value labels.
|
|
13
|
+
transform: { dx: r === 0 ? 0.02 : 0.005, dy: r === 0 ? 0.02 : -0.005 },
|
|
14
|
+
dominantBaseline: r === 0 ? 'hanging' : 'baseline',
|
|
15
|
+
}));
|
|
16
|
+
const interior = [1, -1].flatMap((i) => [...GridLabels.interiorValues].reverse().map((r) => new Tick({
|
|
17
|
+
point: { r, i },
|
|
18
|
+
dp: 1,
|
|
19
|
+
transform: { dx: i * 0.005, dy: -0.005, rotate: i < 0 ? 180 : 0 },
|
|
20
|
+
textAnchor: i < 0 ? 'end' : 'start',
|
|
21
|
+
})));
|
|
22
|
+
return [...axis, ...interior];
|
|
23
|
+
}
|
|
24
|
+
static reactance() {
|
|
25
|
+
return [1, -1].flatMap((sign) => [
|
|
26
|
+
...GridLabels.interiorValues.map((i) => ({ r: 1, i: sign * i })),
|
|
27
|
+
...GridLabels.values.map((i) => ({ r: 0, i: sign * i })),
|
|
28
|
+
].map((point) => new Tick({
|
|
29
|
+
point,
|
|
30
|
+
dp: Math.abs(point.i) >= 10 ? 0 : 1,
|
|
31
|
+
transform: {
|
|
32
|
+
dx: -sign * 0.005,
|
|
33
|
+
dy: -0.005,
|
|
34
|
+
rotate: sign > 0
|
|
35
|
+
? point.r === 1 || point.i < 1
|
|
36
|
+
? 180
|
|
37
|
+
: 0
|
|
38
|
+
: point.r === 0 && point.i < -1
|
|
39
|
+
? 180
|
|
40
|
+
: 0,
|
|
41
|
+
},
|
|
42
|
+
textAnchor: sign > 0 ? 'end' : 'start',
|
|
43
|
+
})));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SmithGridLayer } from './SmithGridLayer.js';
|
|
2
|
+
import type { GridDetail, GridLayer, GridStyle } from '../layers.js';
|
|
3
|
+
import { LayerControl } from './LayerControl.js';
|
|
4
|
+
/** Exposes grid controls without exposing the SVG renderer. */
|
|
5
|
+
export declare class GridLayerControl extends LayerControl implements GridLayer {
|
|
6
|
+
private readonly layer;
|
|
7
|
+
private readonly changed;
|
|
8
|
+
constructor(layer: SmithGridLayer, assertAlive: () => void, changed: () => void);
|
|
9
|
+
setVisible(visible: boolean): void;
|
|
10
|
+
setLabelsVisible(visible: boolean): void;
|
|
11
|
+
setDetail(detail: GridDetail): void;
|
|
12
|
+
setStyle(style: Partial<GridStyle>): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { LayerControl } from './LayerControl.js';
|
|
2
|
+
/** Exposes grid controls without exposing the SVG renderer. */
|
|
3
|
+
export class GridLayerControl extends LayerControl {
|
|
4
|
+
layer;
|
|
5
|
+
changed;
|
|
6
|
+
constructor(layer, assertAlive, changed) {
|
|
7
|
+
super(assertAlive);
|
|
8
|
+
this.layer = layer;
|
|
9
|
+
this.changed = changed;
|
|
10
|
+
}
|
|
11
|
+
setVisible(visible) {
|
|
12
|
+
this.assertAlive();
|
|
13
|
+
this.layer.visibility(visible);
|
|
14
|
+
this.changed();
|
|
15
|
+
}
|
|
16
|
+
setLabelsVisible(visible) {
|
|
17
|
+
this.assertAlive();
|
|
18
|
+
this.layer.setLabelsVisible(visible);
|
|
19
|
+
this.changed();
|
|
20
|
+
}
|
|
21
|
+
setDetail(detail) {
|
|
22
|
+
this.assertAlive();
|
|
23
|
+
if (!['basic', 'standard', 'detailed'].includes(detail)) {
|
|
24
|
+
throw new RangeError('Grid detail must be basic, standard, or detailed.');
|
|
25
|
+
}
|
|
26
|
+
this.layer.setDetail(detail);
|
|
27
|
+
this.changed();
|
|
28
|
+
}
|
|
29
|
+
setStyle(style) {
|
|
30
|
+
this.assertAlive();
|
|
31
|
+
this.validateLengths(style, ['majorWidth', 'minorWidth', 'textFontSize']);
|
|
32
|
+
const properties = {
|
|
33
|
+
stroke: 'Stroke',
|
|
34
|
+
majorWidth: 'MajorWidth',
|
|
35
|
+
minorWidth: 'MinorWidth',
|
|
36
|
+
textColor: 'TextColor',
|
|
37
|
+
textFontFamily: 'TextFontFamily',
|
|
38
|
+
textFontSize: 'TextFontSize',
|
|
39
|
+
};
|
|
40
|
+
for (const key of Object.keys(properties)) {
|
|
41
|
+
const value = style[key];
|
|
42
|
+
if (value !== undefined) {
|
|
43
|
+
this.layer[properties[key]] = String(value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
this.changed();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Shared lifecycle and style validation for chart layer adapters. */
|
|
2
|
+
export declare abstract class LayerControl {
|
|
3
|
+
protected readonly assertAlive: () => void;
|
|
4
|
+
protected constructor(assertAlive: () => void);
|
|
5
|
+
protected validateLengths<T>(style: T, keys: readonly (keyof T)[]): void;
|
|
6
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Shared lifecycle and style validation for chart layer adapters. */
|
|
2
|
+
export class LayerControl {
|
|
3
|
+
assertAlive;
|
|
4
|
+
constructor(assertAlive) {
|
|
5
|
+
this.assertAlive = assertAlive;
|
|
6
|
+
}
|
|
7
|
+
validateLengths(style, keys) {
|
|
8
|
+
for (const key of keys) {
|
|
9
|
+
const value = style[key];
|
|
10
|
+
if (value !== undefined &&
|
|
11
|
+
(typeof value !== 'number' || !Number.isFinite(value) || value <= 0)) {
|
|
12
|
+
throw new RangeError(`${String(key)} must be a positive finite number.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ConstCircles } from './ConstCircles.js';
|
|
2
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
3
|
+
import type { SmithScaler } from '../svg/SmithScaler.js';
|
|
4
|
+
import type { SmithTicksData } from './types.js';
|
|
5
|
+
import { type GridKind } from './GridGeometry.js';
|
|
6
|
+
import type { GridDetail } from '../layers.js';
|
|
7
|
+
export interface GridLayerParams {
|
|
8
|
+
scaler: SmithScaler;
|
|
9
|
+
detail: GridDetail;
|
|
10
|
+
data: SmithTicksData;
|
|
11
|
+
}
|
|
12
|
+
/** SVG adapter shared by the four constant impedance/admittance layers. */
|
|
13
|
+
export declare class SmithGridLayer extends ConstCircles {
|
|
14
|
+
private kind;
|
|
15
|
+
protected major: SmithGroup;
|
|
16
|
+
protected minor: SmithGroup;
|
|
17
|
+
protected texts: SmithGroup;
|
|
18
|
+
private readonly standardDefinitions;
|
|
19
|
+
private readonly basicDefinitions;
|
|
20
|
+
private detail;
|
|
21
|
+
constructor(params: GridLayerParams, kind: GridKind);
|
|
22
|
+
setLabelsVisible(visible: boolean): void;
|
|
23
|
+
setDetail(detail: GridDetail): void;
|
|
24
|
+
private static labelPriority;
|
|
25
|
+
private drawGrid;
|
|
26
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ConstCircles } from './ConstCircles.js';
|
|
2
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
3
|
+
import { SmithText } from '../svg/SmithText.js';
|
|
4
|
+
import { GridGeometry } from './GridGeometry.js';
|
|
5
|
+
import { GridDefinitions } from './GridDefinitions.js';
|
|
6
|
+
import { GridLabels } from './GridLabels.js';
|
|
7
|
+
/** SVG adapter shared by the four constant impedance/admittance layers. */
|
|
8
|
+
export class SmithGridLayer extends ConstCircles {
|
|
9
|
+
kind;
|
|
10
|
+
major;
|
|
11
|
+
minor;
|
|
12
|
+
texts;
|
|
13
|
+
standardDefinitions;
|
|
14
|
+
basicDefinitions;
|
|
15
|
+
detail = 'detailed';
|
|
16
|
+
constructor(params, kind) {
|
|
17
|
+
super(params.scaler);
|
|
18
|
+
this.kind = kind;
|
|
19
|
+
const real = kind === 'resistance' || kind === 'conductance';
|
|
20
|
+
const definitions = params.data[real ? 'resistance' : 'reactance'];
|
|
21
|
+
this.standardDefinitions = definitions.major;
|
|
22
|
+
this.basicDefinitions = GridDefinitions.basic()[real ? 'resistance' : 'reactance'];
|
|
23
|
+
this.major = this.drawGrid(definitions.major, this.opts.majorWidth);
|
|
24
|
+
this.minor = this.drawGrid(definitions.minor, this.opts.minorWidth);
|
|
25
|
+
this.texts = new SmithGroup()
|
|
26
|
+
.attr('stroke', 'none')
|
|
27
|
+
.attr('font-size', this.opts.textFontSize)
|
|
28
|
+
.attr('font-family', this.opts.textFontFamily)
|
|
29
|
+
.attr('fill', this.opts.textColor);
|
|
30
|
+
for (const tick of real ? GridLabels.resistance() : GridLabels.reactance()) {
|
|
31
|
+
const label = GridGeometry.label(kind, tick.definition);
|
|
32
|
+
const text = new SmithText(this.scaler.point(label.point), label.text, {
|
|
33
|
+
rotate: label.rotate,
|
|
34
|
+
dx: this.scaler.r(label.dx).toString(),
|
|
35
|
+
dy: this.scaler.r(label.dy).toString(),
|
|
36
|
+
textAnchor: label.textAnchor,
|
|
37
|
+
dominantBaseline: label.dominantBaseline,
|
|
38
|
+
});
|
|
39
|
+
text.Element.attr('data-label-priority', SmithGridLayer.labelPriority(tick.definition.point.r, tick.definition.point.i));
|
|
40
|
+
const { r, i } = tick.definition.point;
|
|
41
|
+
const basic = real
|
|
42
|
+
? i === 0 && (r === 0 || GridDefinitions.basicValues.includes(r))
|
|
43
|
+
: r === 0 && GridDefinitions.basicValues.includes(Math.abs(i));
|
|
44
|
+
text.Element.attr('data-basic-label', String(basic));
|
|
45
|
+
this.texts.append(text);
|
|
46
|
+
}
|
|
47
|
+
this.build();
|
|
48
|
+
this.setDetail(params.detail);
|
|
49
|
+
}
|
|
50
|
+
setLabelsVisible(visible) {
|
|
51
|
+
// Keep this separate from whole-layer opacity and detail-specific label filtering.
|
|
52
|
+
this.texts.attr('display', visible ? null : 'none');
|
|
53
|
+
}
|
|
54
|
+
setDetail(detail) {
|
|
55
|
+
if (detail === this.detail) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if ((detail === 'basic') !== (this.detail === 'basic')) {
|
|
59
|
+
this.major.Element.selectAll('*').remove();
|
|
60
|
+
this.drawGrid(detail === 'basic' ? this.basicDefinitions : this.standardDefinitions, this.opts.majorWidth, this.major);
|
|
61
|
+
}
|
|
62
|
+
if (detail === 'detailed') {
|
|
63
|
+
this.minor.show();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this.minor.hide();
|
|
67
|
+
}
|
|
68
|
+
this.texts.Element.selectAll('[data-basic-label="false"]').attr('display', detail === 'basic' ? 'none' : null);
|
|
69
|
+
this.detail = detail;
|
|
70
|
+
}
|
|
71
|
+
static labelPriority(real, imaginary) {
|
|
72
|
+
const value = Math.abs(imaginary === 0 ? real : imaginary);
|
|
73
|
+
const importance = value === 0
|
|
74
|
+
? 300
|
|
75
|
+
: value === 1
|
|
76
|
+
? 100
|
|
77
|
+
: value === 50
|
|
78
|
+
? 90
|
|
79
|
+
: [0.5, 2].includes(value)
|
|
80
|
+
? 80
|
|
81
|
+
: [0.2, 5, 10].includes(value)
|
|
82
|
+
? 70
|
|
83
|
+
: 40;
|
|
84
|
+
return importance + (imaginary === 0 ? 20 : real === 0 ? 10 : 0);
|
|
85
|
+
}
|
|
86
|
+
drawGrid(definitions, width, group = new SmithGroup()) {
|
|
87
|
+
const geometry = GridGeometry.shapes(this.kind, definitions);
|
|
88
|
+
this.drawShapes(group.Element, this.opts.stroke, width, {
|
|
89
|
+
lines: geometry.lines.map((line) => this.scaler.line(line)),
|
|
90
|
+
circles: geometry.circles.map((circle) => this.scaler.circle(circle)),
|
|
91
|
+
arcs: geometry.arcs.map((arc) => this.scaleArc(this.scaler, arc)),
|
|
92
|
+
});
|
|
93
|
+
return group;
|
|
94
|
+
}
|
|
95
|
+
}
|
package/dist/lib/grid/types.d.ts
CHANGED
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
export { Smith, SmithEventType } from './Smith.js';
|
|
2
2
|
export type { SmithEvent } from './Smith.js';
|
|
3
|
-
export { Complex } from './
|
|
3
|
+
export { Complex } from './math/Complex.js';
|
|
4
4
|
export type { TraceSamples, TraceSample } from './samples.js';
|
|
5
|
-
export {
|
|
6
|
-
export type { TouchstoneData } from './io/
|
|
5
|
+
export { Touchstone } from './io/Touchstone.js';
|
|
6
|
+
export type { TouchstoneData } from './io/Touchstone.js';
|
|
7
7
|
export { SmithScales } from './scales/SmithScales.js';
|
|
8
|
-
export {
|
|
8
|
+
export { MarkerMeasurements } from './MarkerMeasurements.js';
|
|
9
9
|
export type { TraceOptions, TraceUpdateOptions, MarkerSelectionStrategy, TraceStyle, TraceRenderMode, TraceInfo, MarkerInfo, MarkerSnapshot, MarkerComparison, } from './measurements.js';
|
|
10
|
-
export {
|
|
11
|
-
export type { SmithReading } from './rf.js';
|
|
12
|
-
export type { GridStyle, CircleStyle, GridLayer, CircleLayer, ChartLayers, PeripheralScales, } from './layers.js';
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
16
|
-
export type {
|
|
10
|
+
export { RfCalculations } from './rf/RfCalculations.js';
|
|
11
|
+
export type { SmithReading } from './rf/RfCalculations.js';
|
|
12
|
+
export type { GridStyle, CircleStyle, GridLayer, GridDetail, CircleLayer, ChartLayers, PeripheralScales, } from './layers.js';
|
|
13
|
+
export { SmithFormatter } from './SmithFormatter.js';
|
|
14
|
+
export type { ReactiveComponent } from './rf/RfCalculations.js';
|
|
15
|
+
export type { SmithAppearance, SmithTheme, SmithThemeOverrides } from './appearance/types.js';
|
|
16
|
+
export type { MarkerLegendField, MarkerLegendOptions, ImageExportOptions, SmithImageExportOptions, ScaleImageExportOptions, ScaleExportReadout, } from './svg/export.js';
|
package/dist/lib/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export { Smith, SmithEventType } from './Smith.js';
|
|
2
|
-
export { Complex } from './
|
|
3
|
-
export {
|
|
2
|
+
export { Complex } from './math/Complex.js';
|
|
3
|
+
export { Touchstone } from './io/Touchstone.js';
|
|
4
4
|
export { SmithScales } from './scales/SmithScales.js';
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export { formatNumber, formatComplex, formatComplexPolar } from './formatting.js';
|
|
9
|
-
export { reactanceToComponent } from './components.js';
|
|
5
|
+
export { MarkerMeasurements } from './MarkerMeasurements.js';
|
|
6
|
+
export { RfCalculations } from './rf/RfCalculations.js';
|
|
7
|
+
export { SmithFormatter } from './SmithFormatter.js';
|
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithScaler } from '
|
|
3
|
-
import { Complex } from '../
|
|
4
|
-
interface DrawOptions {
|
|
5
|
-
point: {
|
|
6
|
-
radius: number;
|
|
7
|
-
color: string;
|
|
8
|
-
};
|
|
9
|
-
impedance: {
|
|
10
|
-
width: number;
|
|
11
|
-
color: string;
|
|
12
|
-
};
|
|
13
|
-
admittance: {
|
|
14
|
-
width: number;
|
|
15
|
-
color: string;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithScaler } from '../svg/SmithScaler.js';
|
|
3
|
+
import { Complex } from '../math/Complex.js';
|
|
18
4
|
export declare class SmithCursor {
|
|
19
5
|
private scaler;
|
|
20
6
|
private epsilon;
|
|
21
7
|
private pendingMove;
|
|
22
|
-
private drawingOpts;
|
|
23
8
|
private calcs;
|
|
24
9
|
private zClipCircle;
|
|
25
10
|
private yClipCircle;
|
|
@@ -44,6 +29,4 @@ export declare class SmithCursor {
|
|
|
44
29
|
hide(): void;
|
|
45
30
|
private cancelPendingMove;
|
|
46
31
|
setMoveHandler(handler: ((rc: Complex) => void) | null): void;
|
|
47
|
-
setDrawOptions(opts: DrawOptions): void;
|
|
48
32
|
}
|
|
49
|
-
export {};
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithCircle } from '
|
|
3
|
-
import { SmithLine } from '
|
|
4
|
-
import { SmithArc } from '
|
|
5
|
-
import { SmithConstantCircle } from '../SmithConstantCircle.js';
|
|
6
|
-
import { Complex } from '../
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithCircle } from '../svg/SmithCircle.js';
|
|
3
|
+
import { SmithLine } from '../svg/SmithLine.js';
|
|
4
|
+
import { SmithArc } from '../svg/SmithArc.js';
|
|
5
|
+
import { SmithConstantCircle } from '../rf/SmithConstantCircle.js';
|
|
6
|
+
import { Complex } from '../math/Complex.js';
|
|
7
7
|
export class SmithCursor {
|
|
8
8
|
scaler;
|
|
9
9
|
epsilon = 1.5e-4;
|
|
10
10
|
pendingMove;
|
|
11
|
-
drawingOpts = {
|
|
12
|
-
point: { radius: 5, color: 'red' },
|
|
13
|
-
impedance: { width: 1, color: 'red' },
|
|
14
|
-
admittance: { width: 1, color: 'green' },
|
|
15
|
-
};
|
|
16
11
|
calcs = new SmithConstantCircle();
|
|
17
12
|
zClipCircle = this.calcs.resistanceCircle(0);
|
|
18
13
|
yClipCircle = this.calcs.conductanceCircle(0);
|
|
@@ -27,8 +22,8 @@ export class SmithCursor {
|
|
|
27
22
|
this.group = new SmithGroup().attr('pointer-events', 'none');
|
|
28
23
|
this.impedance = {
|
|
29
24
|
group: new SmithGroup({
|
|
30
|
-
stroke:
|
|
31
|
-
strokeWidth:
|
|
25
|
+
stroke: 'var(--smithkit-cursor-impedanceColor)',
|
|
26
|
+
strokeWidth: 'var(--smithkit-cursor-lineWidth)',
|
|
32
27
|
fill: 'none',
|
|
33
28
|
}),
|
|
34
29
|
resistance: { circle: new SmithCircle({ p: [0, 0], r: 1 }) },
|
|
@@ -42,8 +37,8 @@ export class SmithCursor {
|
|
|
42
37
|
this.impedance.reactance.line.nonScalingStroke();
|
|
43
38
|
this.admittance = {
|
|
44
39
|
group: new SmithGroup({
|
|
45
|
-
stroke:
|
|
46
|
-
strokeWidth:
|
|
40
|
+
stroke: 'var(--smithkit-cursor-admittanceColor)',
|
|
41
|
+
strokeWidth: 'var(--smithkit-cursor-lineWidth)',
|
|
47
42
|
fill: 'none',
|
|
48
43
|
}),
|
|
49
44
|
conductance: { circle: new SmithCircle({ p: [0, 0], r: 1 }) },
|
|
@@ -56,8 +51,8 @@ export class SmithCursor {
|
|
|
56
51
|
this.admittance.susceptance.arc.nonScalingStroke();
|
|
57
52
|
this.admittance.susceptance.line.nonScalingStroke();
|
|
58
53
|
this.point = new SmithLine([0, 0], [0, 0], {
|
|
59
|
-
stroke:
|
|
60
|
-
strokeWidth:
|
|
54
|
+
stroke: 'var(--smithkit-cursor-pointColor)',
|
|
55
|
+
strokeWidth: 'var(--smithkit-cursor-pointSize)',
|
|
61
56
|
fill: 'none',
|
|
62
57
|
});
|
|
63
58
|
this.point.nonScalingStroke();
|
|
@@ -180,7 +175,4 @@ export class SmithCursor {
|
|
|
180
175
|
this.cancelPendingMove();
|
|
181
176
|
}
|
|
182
177
|
}
|
|
183
|
-
setDrawOptions(opts) {
|
|
184
|
-
this.drawingOpts = opts;
|
|
185
|
-
}
|
|
186
178
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TraceSamples } from '../samples.js';
|
|
2
|
+
export interface TouchstoneData {
|
|
3
|
+
samples: TraceSamples;
|
|
4
|
+
referenceImpedanceOhms: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class Touchstone {
|
|
7
|
+
private constructor();
|
|
8
|
+
/** Read one-port Touchstone 1.x data; frequencies in the result are always Hz. */
|
|
9
|
+
static parse(text: string): TouchstoneData;
|
|
10
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export class Touchstone {
|
|
2
|
+
constructor() { }
|
|
3
|
+
/** Read one-port Touchstone 1.x data; frequencies in the result are always Hz. */
|
|
4
|
+
static parse(text) {
|
|
5
|
+
const units = { HZ: 1, KHZ: 1e3, MHZ: 1e6, GHZ: 1e9 };
|
|
6
|
+
let frequencyScale = 1e9;
|
|
7
|
+
let format = 'MA';
|
|
8
|
+
let referenceImpedanceOhms = 50;
|
|
9
|
+
let optionsSeen = false;
|
|
10
|
+
const samples = [];
|
|
11
|
+
for (const [index, raw] of text
|
|
12
|
+
.replace(/^\uFEFF/, '')
|
|
13
|
+
.split(/\r?\n/)
|
|
14
|
+
.entries()) {
|
|
15
|
+
const line = raw.split('!')[0].trim();
|
|
16
|
+
if (!line) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const fail = (message) => {
|
|
20
|
+
throw new Error(`Line ${index + 1}: ${message}`);
|
|
21
|
+
};
|
|
22
|
+
if (line.startsWith('[')) {
|
|
23
|
+
fail('Only Touchstone 1.x one-port files (.s1p) are supported.');
|
|
24
|
+
}
|
|
25
|
+
if (line.startsWith('#')) {
|
|
26
|
+
if (optionsSeen || samples.length) {
|
|
27
|
+
fail('The option line must appear once, before the data.');
|
|
28
|
+
}
|
|
29
|
+
optionsSeen = true;
|
|
30
|
+
const options = line.slice(1).trim().toUpperCase().split(/\s+/).filter(Boolean);
|
|
31
|
+
if (!options.length) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const [unit = 'GHZ', parameter = 'S', representation = 'MA', r = 'R', impedance = '50'] = options;
|
|
35
|
+
if (!(unit in units) ||
|
|
36
|
+
parameter !== 'S' ||
|
|
37
|
+
!['RI', 'MA', 'DB'].includes(representation) ||
|
|
38
|
+
r !== 'R' ||
|
|
39
|
+
options.length > 5) {
|
|
40
|
+
fail('Expected: # Hz|kHz|MHz|GHz S RI|MA|DB R impedance.');
|
|
41
|
+
}
|
|
42
|
+
frequencyScale = units[unit];
|
|
43
|
+
format = representation;
|
|
44
|
+
referenceImpedanceOhms = Number(impedance);
|
|
45
|
+
if (!Number.isFinite(referenceImpedanceOhms) || referenceImpedanceOhms <= 0) {
|
|
46
|
+
fail('Reference impedance must be positive.');
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const fields = line.split(/\s+/).map(Number);
|
|
51
|
+
if (fields.length !== 3 || !fields.every(Number.isFinite)) {
|
|
52
|
+
fail('Expected frequency and two finite S11 components.');
|
|
53
|
+
}
|
|
54
|
+
const [frequency, a, b] = fields;
|
|
55
|
+
const frequencyHz = frequency * frequencyScale;
|
|
56
|
+
if (frequencyHz < 0 || !Number.isFinite(frequencyHz)) {
|
|
57
|
+
fail('Frequency must be finite and non-negative.');
|
|
58
|
+
}
|
|
59
|
+
if (format === 'MA' && a < 0) {
|
|
60
|
+
fail('Magnitude must be non-negative.');
|
|
61
|
+
}
|
|
62
|
+
const magnitude = format === 'DB' ? 10 ** (a / 20) : a;
|
|
63
|
+
const radians = (b * Math.PI) / 180;
|
|
64
|
+
const reflectionCoefficient = format === 'RI' ? [a, b] : [magnitude * Math.cos(radians), magnitude * Math.sin(radians)];
|
|
65
|
+
if (!reflectionCoefficient.every(Number.isFinite)) {
|
|
66
|
+
fail('S11 is outside the supported numeric range.');
|
|
67
|
+
}
|
|
68
|
+
samples.push({ frequencyHz, reflectionCoefficient });
|
|
69
|
+
}
|
|
70
|
+
if (!samples.length) {
|
|
71
|
+
throw new Error('The file contains no S11 samples.');
|
|
72
|
+
}
|
|
73
|
+
return { samples, referenceImpedanceOhms };
|
|
74
|
+
}
|
|
75
|
+
}
|
package/dist/lib/layers.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ConstQCircles } from './draw/ConstQCircles.js';
|
|
3
|
-
import type { ConstSwrCircles } from './draw/ConstSwrCircles.js';
|
|
4
|
-
import type { Complex } from './complex/Complex.js';
|
|
1
|
+
import type { Complex } from './math/Complex.js';
|
|
5
2
|
export interface GridStyle {
|
|
6
3
|
stroke: string;
|
|
7
4
|
/** Non-scaling stroke width in CSS pixels. */
|
|
@@ -10,7 +7,7 @@ export interface GridStyle {
|
|
|
10
7
|
minorWidth: number;
|
|
11
8
|
textColor: string;
|
|
12
9
|
textFontFamily: string;
|
|
13
|
-
/**
|
|
10
|
+
/** Base font size in chart units; adaptive layout enforces a 9 CSS px minimum in the default view. */
|
|
14
11
|
textFontSize: number;
|
|
15
12
|
}
|
|
16
13
|
export interface CircleStyle {
|
|
@@ -18,10 +15,14 @@ export interface CircleStyle {
|
|
|
18
15
|
/** Non-scaling stroke width in CSS pixels. */
|
|
19
16
|
strokeWidth: number;
|
|
20
17
|
}
|
|
18
|
+
export type GridDetail = 'basic' | 'standard' | 'detailed';
|
|
21
19
|
/** Grid styling uses SVG user units, except non-scaling stroke widths in screen pixels. */
|
|
22
20
|
export interface GridLayer {
|
|
23
21
|
setVisible(visible: boolean): void;
|
|
24
|
-
|
|
22
|
+
/** Show or hide labels independently of grid lines. Default: true. */
|
|
23
|
+
setLabelsVisible(visible: boolean): void;
|
|
24
|
+
/** Default: detailed. Basic shows only the principal normalized values. */
|
|
25
|
+
setDetail(detail: GridDetail): void;
|
|
25
26
|
setStyle(style: Partial<GridStyle>): void;
|
|
26
27
|
}
|
|
27
28
|
export interface CircleLayer {
|
|
@@ -43,6 +44,3 @@ export interface PeripheralScales {
|
|
|
43
44
|
/** Pass null to clear the indicators. */
|
|
44
45
|
update(reflectionCoefficient: Complex | null): void;
|
|
45
46
|
}
|
|
46
|
-
/** Keep renderer instances out of the public chart API. */
|
|
47
|
-
export declare function gridLayer(layer: ConstCircles, assertAlive: () => void): GridLayer;
|
|
48
|
-
export declare function circleLayer(layer: ConstQCircles | ConstSwrCircles, minimum: number, assertAlive: () => void): CircleLayer;
|
package/dist/lib/layers.js
CHANGED
|
@@ -1,73 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export function gridLayer(layer, assertAlive) {
|
|
3
|
-
return {
|
|
4
|
-
setVisible(visible) {
|
|
5
|
-
assertAlive();
|
|
6
|
-
layer.visibility(visible);
|
|
7
|
-
},
|
|
8
|
-
setMinorVisible(visible) {
|
|
9
|
-
assertAlive();
|
|
10
|
-
layer.displayMinor(visible);
|
|
11
|
-
},
|
|
12
|
-
setStyle(style) {
|
|
13
|
-
assertAlive();
|
|
14
|
-
validateLengths(style, ['majorWidth', 'minorWidth', 'textFontSize']);
|
|
15
|
-
const properties = {
|
|
16
|
-
stroke: 'Stroke',
|
|
17
|
-
majorWidth: 'MajorWidth',
|
|
18
|
-
minorWidth: 'MinorWidth',
|
|
19
|
-
textColor: 'TextColor',
|
|
20
|
-
textFontFamily: 'TextFontFamily',
|
|
21
|
-
textFontSize: 'TextFontSize',
|
|
22
|
-
};
|
|
23
|
-
for (const key of Object.keys(properties)) {
|
|
24
|
-
const value = style[key];
|
|
25
|
-
if (value !== undefined) {
|
|
26
|
-
layer[properties[key]] = String(value);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
export function circleLayer(layer, minimum, assertAlive) {
|
|
33
|
-
const validate = (value) => {
|
|
34
|
-
if (!Number.isFinite(value) || value < minimum || value <= 0) {
|
|
35
|
-
throw new RangeError(`Circle value must be finite, positive, and at least ${minimum}.`);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
return {
|
|
39
|
-
setVisible(visible) {
|
|
40
|
-
assertAlive();
|
|
41
|
-
layer.visibility(visible);
|
|
42
|
-
},
|
|
43
|
-
setStyle(style) {
|
|
44
|
-
assertAlive();
|
|
45
|
-
validateLengths(style, ['strokeWidth']);
|
|
46
|
-
if (style.stroke !== undefined) {
|
|
47
|
-
layer.Stroke = style.stroke;
|
|
48
|
-
}
|
|
49
|
-
if (style.strokeWidth !== undefined) {
|
|
50
|
-
layer.StrokeWidth = String(style.strokeWidth);
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
addValue(value) {
|
|
54
|
-
assertAlive();
|
|
55
|
-
validate(value);
|
|
56
|
-
layer.append(value);
|
|
57
|
-
},
|
|
58
|
-
removeValue(value) {
|
|
59
|
-
assertAlive();
|
|
60
|
-
validate(value);
|
|
61
|
-
layer.remove(value);
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function validateLengths(style, keys) {
|
|
66
|
-
for (const key of keys) {
|
|
67
|
-
const value = style[key];
|
|
68
|
-
if (value !== undefined &&
|
|
69
|
-
(typeof value !== 'number' || !Number.isFinite(value) || value <= 0)) {
|
|
70
|
-
throw new RangeError(`${String(key)} must be a positive finite number.`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
1
|
+
export {};
|
|
@@ -126,5 +126,6 @@ export declare class Complex {
|
|
|
126
126
|
static equals(z1: Complex, z2: Complex, epsilon?: number): boolean;
|
|
127
127
|
static toPolar(z: Complex): [number, number];
|
|
128
128
|
static toVector(z: Complex): [number, number];
|
|
129
|
+
/** Format Cartesian components with Number.toFixed(dp), defaulting to three decimal places. */
|
|
129
130
|
static toString(z: Complex, dp?: number): string;
|
|
130
131
|
}
|
|
@@ -626,7 +626,7 @@ export class Complex {
|
|
|
626
626
|
static toVector(z) {
|
|
627
627
|
return [z.re, z.im];
|
|
628
628
|
}
|
|
629
|
-
|
|
629
|
+
/** Format Cartesian components with Number.toFixed(dp), defaulting to three decimal places. */
|
|
630
630
|
static toString(z, dp = 3) {
|
|
631
631
|
const re = z.re.toFixed(dp);
|
|
632
632
|
const im = Math.abs(z.im).toFixed(dp);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Complex } from './
|
|
2
|
-
import type { SmithReading } from './rf.js';
|
|
1
|
+
import { Complex } from './math/Complex.js';
|
|
2
|
+
import type { SmithReading } from './rf/RfCalculations.js';
|
|
3
3
|
export type TraceRenderMode = 'points' | 'line' | 'both';
|
|
4
4
|
export interface TraceStyle {
|
|
5
5
|
mode: TraceRenderMode;
|
|
@@ -49,5 +49,3 @@ export interface MarkerComparison {
|
|
|
49
49
|
/** Shortest signed B − A phase difference in [−180, 180); undefined at Γ = 0. */
|
|
50
50
|
readonly phaseDeltaDegrees: number | undefined;
|
|
51
51
|
}
|
|
52
|
-
/** Compare B against A without a chart or browser. Frequencies must be finite and non-negative. */
|
|
53
|
-
export declare function compareMarkerReadings(a: Pick<MarkerSnapshot, 'frequencyHz' | 'impedanceOhms' | 'reflectionCoefficient'>, b: Pick<MarkerSnapshot, 'frequencyHz' | 'impedanceOhms' | 'reflectionCoefficient'>): MarkerComparison;
|