smithkit 0.1.0 → 0.2.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 +124 -59
- package/dist/lib/MarkerMeasurements.d.ts +6 -0
- package/dist/lib/MarkerMeasurements.js +22 -0
- package/dist/lib/Smith.d.ts +9 -2
- package/dist/lib/Smith.js +78 -35
- package/dist/lib/SmithFormatter.d.ts +10 -0
- package/dist/lib/SmithFormatter.js +19 -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 +6 -6
- package/dist/lib/{draw → grid}/ConstCircles.js +12 -5
- package/dist/lib/{draw → grid}/ConstQCircles.d.ts +2 -2
- package/dist/lib/{draw → grid}/ConstQCircles.js +3 -3
- package/dist/lib/{draw → grid}/ConstSwrCircles.d.ts +2 -2
- package/dist/lib/{draw → grid}/ConstSwrCircles.js +3 -3
- package/dist/lib/grid/GridDefinitions.d.ts +12 -0
- package/dist/lib/grid/GridDefinitions.js +138 -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 +12 -0
- package/dist/lib/grid/GridLayerControl.js +39 -0
- package/dist/lib/grid/LayerControl.d.ts +6 -0
- package/dist/lib/grid/LayerControl.js +16 -0
- package/dist/lib/{draw → grid}/SmithGridLayer.d.ts +5 -4
- package/dist/lib/{draw → grid}/SmithGridLayer.js +26 -9
- package/dist/lib/grid/types.d.ts +1 -1
- package/dist/lib/index.d.ts +8 -10
- package/dist/lib/index.js +5 -7
- package/dist/lib/{draw → interaction}/SmithCursor.d.ts +3 -3
- package/dist/lib/{draw → interaction}/SmithCursor.js +6 -6
- package/dist/lib/io/Touchstone.d.ts +10 -0
- package/dist/lib/io/Touchstone.js +75 -0
- package/dist/lib/layers.d.ts +2 -8
- 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/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 +7 -2
- package/dist/lib/scales/SmithPeripheralScales.js +65 -28
- package/dist/lib/scales/SmithScales.d.ts +3 -1
- package/dist/lib/scales/SmithScales.js +20 -6
- package/dist/lib/svg/LabelLayout.d.ts +17 -0
- package/dist/lib/svg/LabelLayout.js +145 -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 +14 -0
- package/dist/lib/svg/SvgExporter.js +137 -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 +237 -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/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/Circle.js +0 -1
- package/dist/lib/shapes/Line.d.ts +0 -5
- package/dist/lib/shapes/Line.js +0 -1
- package/dist/lib/shapes/Point.d.ts +0 -1
- package/dist/lib/shapes/Point.js +0 -1
- /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/{draw/SmithDrawOptions.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/Arc.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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { TraceSamples } from '../samples.js';
|
|
2
|
+
import { Complex } from '../math/Complex.js';
|
|
3
|
+
/** Physical quantities derived from a voltage reflection coefficient Γ. */
|
|
4
|
+
export interface SmithReading {
|
|
5
|
+
readonly reflectionCoefficient: Complex;
|
|
6
|
+
readonly impedanceOhms: Complex | undefined;
|
|
7
|
+
readonly admittanceSiemens: Complex | undefined;
|
|
8
|
+
readonly phaseDegrees: number | undefined;
|
|
9
|
+
readonly vswr: number | undefined;
|
|
10
|
+
readonly standingWaveRatioDb: number | undefined;
|
|
11
|
+
readonly returnLossDb: number;
|
|
12
|
+
readonly reflectionLossDb: number | undefined;
|
|
13
|
+
readonly attenuationDb: number | undefined;
|
|
14
|
+
readonly q: number | undefined;
|
|
15
|
+
readonly powerReflectionCoefficient: number;
|
|
16
|
+
readonly voltageReflectionCoefficientMagnitude: number;
|
|
17
|
+
readonly powerTransmissionCoefficient: number | undefined;
|
|
18
|
+
readonly voltageTransmissionCoefficientMagnitude: number;
|
|
19
|
+
readonly currentTransmissionCoefficientMagnitude: number;
|
|
20
|
+
readonly standingWavePeak: number | undefined;
|
|
21
|
+
readonly standingWaveLossCoefficient: number | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** An ideal series component equivalent to a reactance at one frequency. */
|
|
24
|
+
export type ReactiveComponent = {
|
|
25
|
+
readonly kind: 'inductor';
|
|
26
|
+
readonly inductanceHenries: number;
|
|
27
|
+
} | {
|
|
28
|
+
readonly kind: 'capacitor';
|
|
29
|
+
readonly capacitanceFarads: number;
|
|
30
|
+
};
|
|
31
|
+
export declare class RfCalculations {
|
|
32
|
+
private constructor();
|
|
33
|
+
private static readonly calcs;
|
|
34
|
+
private static validateReference;
|
|
35
|
+
private static validateComplex;
|
|
36
|
+
private static finite;
|
|
37
|
+
/** Convert Γ to physical impedance in ohms; undefined at the open circuit Γ = 1. */
|
|
38
|
+
static reflectionToImpedance(gamma: Complex, referenceImpedanceOhms?: number): Complex | undefined;
|
|
39
|
+
/** Convert physical impedance in ohms to Γ. Undefined for a singular result. */
|
|
40
|
+
static impedanceToReflection(impedanceOhms: Complex, referenceImpedanceOhms?: number): Complex | undefined;
|
|
41
|
+
/** Convert Γ to physical admittance in siemens; undefined at the short circuit Γ = −1. */
|
|
42
|
+
static reflectionToAdmittance(gamma: Complex, referenceImpedanceOhms?: number): Complex | undefined;
|
|
43
|
+
/** Convert physical admittance in siemens to Γ. Undefined for a singular result. */
|
|
44
|
+
static admittanceToReflection(admittanceSiemens: Complex, referenceImpedanceOhms?: number): Complex | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Read Γ without a chart or DOM. Undefined means a singular or inapplicable quantity.
|
|
47
|
+
* Passive-load quantities are undefined outside |Γ| ≤ 1; exact infinite limits are retained.
|
|
48
|
+
* Attenuation assumes a fully reflecting termination and is half the return loss.
|
|
49
|
+
*/
|
|
50
|
+
static readReflection(gamma: Complex, referenceImpedanceOhms?: number): SmithReading;
|
|
51
|
+
/**
|
|
52
|
+
* Change the positive real reference impedance of a voltage reflection coefficient.
|
|
53
|
+
* Preserves physical impedance, including exact open/short limits. A singular or
|
|
54
|
+
* unrepresentable result is undefined; non-finite inputs throw RangeError.
|
|
55
|
+
*/
|
|
56
|
+
static renormalizeReflection(gamma: Complex, fromOhms: number, toOhms: number): Complex | undefined;
|
|
57
|
+
/** Copy and renormalize every sample; reject invalid/singular data without modifying the input. */
|
|
58
|
+
static renormalizeSamples(samples: TraceSamples, fromOhms: number, toOhms: number): TraceSamples;
|
|
59
|
+
/**
|
|
60
|
+
* Convert reactance in ohms at a frequency in Hz to an ideal series L or C.
|
|
61
|
+
* Zero frequency, zero reactance, or an unrepresentable component returns undefined.
|
|
62
|
+
* Non-finite reactance and negative/non-finite frequency throw RangeError.
|
|
63
|
+
*/
|
|
64
|
+
static reactanceToComponent(reactanceOhms: number, frequencyHz: number): ReactiveComponent | undefined;
|
|
65
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Complex } from '../math/Complex.js';
|
|
2
|
+
import { SmithConstantCircle } from './SmithConstantCircle.js';
|
|
3
|
+
export class RfCalculations {
|
|
4
|
+
constructor() { }
|
|
5
|
+
static calcs = new SmithConstantCircle();
|
|
6
|
+
static validateReference(referenceImpedanceOhms) {
|
|
7
|
+
if (!Number.isFinite(referenceImpedanceOhms) || referenceImpedanceOhms <= 0) {
|
|
8
|
+
throw new RangeError('Reference impedance must be positive and finite.');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
static validateComplex(value) {
|
|
12
|
+
if (!Number.isFinite(value.re) || !Number.isFinite(value.im)) {
|
|
13
|
+
throw new RangeError('Complex components must be finite.');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
static finite(value) {
|
|
17
|
+
return value && Number.isFinite(value.re) && Number.isFinite(value.im) ? value : undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Convert Γ to physical impedance in ohms; undefined at the open circuit Γ = 1. */
|
|
20
|
+
static reflectionToImpedance(gamma, referenceImpedanceOhms = 50) {
|
|
21
|
+
RfCalculations.validateReference(referenceImpedanceOhms);
|
|
22
|
+
RfCalculations.validateComplex(gamma);
|
|
23
|
+
return RfCalculations.finite(RfCalculations.calcs.rflCoeffToImpedance(gamma)?.mul(referenceImpedanceOhms));
|
|
24
|
+
}
|
|
25
|
+
/** Convert physical impedance in ohms to Γ. Undefined for a singular result. */
|
|
26
|
+
static impedanceToReflection(impedanceOhms, referenceImpedanceOhms = 50) {
|
|
27
|
+
RfCalculations.validateReference(referenceImpedanceOhms);
|
|
28
|
+
RfCalculations.validateComplex(impedanceOhms);
|
|
29
|
+
return RfCalculations.finite(RfCalculations.calcs.impedanceToRflCoeff(impedanceOhms.div(referenceImpedanceOhms)));
|
|
30
|
+
}
|
|
31
|
+
/** Convert Γ to physical admittance in siemens; undefined at the short circuit Γ = −1. */
|
|
32
|
+
static reflectionToAdmittance(gamma, referenceImpedanceOhms = 50) {
|
|
33
|
+
RfCalculations.validateReference(referenceImpedanceOhms);
|
|
34
|
+
RfCalculations.validateComplex(gamma);
|
|
35
|
+
return RfCalculations.finite(RfCalculations.calcs.rflCoeffToAdmittance(gamma)?.div(referenceImpedanceOhms));
|
|
36
|
+
}
|
|
37
|
+
/** Convert physical admittance in siemens to Γ. Undefined for a singular result. */
|
|
38
|
+
static admittanceToReflection(admittanceSiemens, referenceImpedanceOhms = 50) {
|
|
39
|
+
RfCalculations.validateReference(referenceImpedanceOhms);
|
|
40
|
+
RfCalculations.validateComplex(admittanceSiemens);
|
|
41
|
+
return RfCalculations.finite(RfCalculations.calcs.admittanceToRflCoeff(admittanceSiemens.mul(referenceImpedanceOhms)));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Read Γ without a chart or DOM. Undefined means a singular or inapplicable quantity.
|
|
45
|
+
* Passive-load quantities are undefined outside |Γ| ≤ 1; exact infinite limits are retained.
|
|
46
|
+
* Attenuation assumes a fully reflecting termination and is half the return loss.
|
|
47
|
+
*/
|
|
48
|
+
static readReflection(gamma, referenceImpedanceOhms = 50) {
|
|
49
|
+
const impedanceOhms = RfCalculations.reflectionToImpedance(gamma, referenceImpedanceOhms);
|
|
50
|
+
const admittanceSiemens = RfCalculations.reflectionToAdmittance(gamma, referenceImpedanceOhms);
|
|
51
|
+
const magnitude = gamma.abs();
|
|
52
|
+
const passive = magnitude <= 1;
|
|
53
|
+
const returnLossDb = -20 * Math.log10(magnitude);
|
|
54
|
+
const vswr = passive ? (1 + magnitude) / (1 - magnitude) : undefined;
|
|
55
|
+
return {
|
|
56
|
+
reflectionCoefficient: gamma,
|
|
57
|
+
impedanceOhms,
|
|
58
|
+
admittanceSiemens,
|
|
59
|
+
phaseDegrees: magnitude === 0 ? undefined : (gamma.arg() * 180) / Math.PI,
|
|
60
|
+
vswr,
|
|
61
|
+
standingWaveRatioDb: vswr === undefined ? undefined : 20 * Math.log10(vswr),
|
|
62
|
+
returnLossDb,
|
|
63
|
+
reflectionLossDb: passive ? (-10 / Math.LN10) * Math.log1p(-(magnitude ** 2)) : undefined,
|
|
64
|
+
attenuationDb: passive ? returnLossDb / 2 : undefined,
|
|
65
|
+
q: impedanceOhms && (impedanceOhms.re !== 0 || impedanceOhms.im !== 0)
|
|
66
|
+
? Math.abs(impedanceOhms.im / impedanceOhms.re)
|
|
67
|
+
: undefined,
|
|
68
|
+
powerReflectionCoefficient: magnitude ** 2,
|
|
69
|
+
voltageReflectionCoefficientMagnitude: magnitude,
|
|
70
|
+
powerTransmissionCoefficient: passive ? 1 - magnitude ** 2 : undefined,
|
|
71
|
+
voltageTransmissionCoefficientMagnitude: gamma.add(1).abs(),
|
|
72
|
+
currentTransmissionCoefficientMagnitude: Complex.one().sub(gamma).abs(),
|
|
73
|
+
standingWavePeak: vswr === undefined ? undefined : Math.sqrt(vswr),
|
|
74
|
+
standingWaveLossCoefficient: passive
|
|
75
|
+
? (1 + magnitude ** 2) / (1 - magnitude ** 2)
|
|
76
|
+
: undefined,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Change the positive real reference impedance of a voltage reflection coefficient.
|
|
81
|
+
* Preserves physical impedance, including exact open/short limits. A singular or
|
|
82
|
+
* unrepresentable result is undefined; non-finite inputs throw RangeError.
|
|
83
|
+
*/
|
|
84
|
+
static renormalizeReflection(gamma, fromOhms, toOhms) {
|
|
85
|
+
RfCalculations.validateReference(fromOhms);
|
|
86
|
+
RfCalculations.validateReference(toOhms);
|
|
87
|
+
if (!Number.isFinite(gamma.re) || !Number.isFinite(gamma.im)) {
|
|
88
|
+
throw new RangeError('Reflection coefficient components must be finite.');
|
|
89
|
+
}
|
|
90
|
+
if (fromOhms === toOhms || (gamma.im === 0 && Math.abs(gamma.re) === 1)) {
|
|
91
|
+
return gamma;
|
|
92
|
+
}
|
|
93
|
+
// Γnew = (Γold + k) / (1 + k Γold). Scale references before summing.
|
|
94
|
+
const referenceScale = Math.max(fromOhms, toOhms);
|
|
95
|
+
const from = fromOhms / referenceScale;
|
|
96
|
+
const to = toOhms / referenceScale;
|
|
97
|
+
const k = (fromOhms - toOhms) / referenceScale / (from + to);
|
|
98
|
+
const scale = Math.max(1, Math.abs(gamma.re), Math.abs(gamma.im));
|
|
99
|
+
const x = gamma.re / scale;
|
|
100
|
+
const y = gamma.im / scale;
|
|
101
|
+
const inverseScale = 1 / scale;
|
|
102
|
+
const nr = x + k * inverseScale;
|
|
103
|
+
const dr = inverseScale + k * x;
|
|
104
|
+
const di = k * y;
|
|
105
|
+
const denominatorScale = Math.max(Math.abs(dr), Math.abs(di));
|
|
106
|
+
if (denominatorScale === 0) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const real = dr / denominatorScale;
|
|
110
|
+
const imaginary = di / denominatorScale;
|
|
111
|
+
const denominator = real ** 2 + imaginary ** 2;
|
|
112
|
+
const re = ((nr / denominatorScale) * real + (y / denominatorScale) * imaginary) / denominator;
|
|
113
|
+
// Analytic imaginary numerator avoids cancellation for very large finite Γ.
|
|
114
|
+
const im = (((1 - k) * (1 + k) * (y / denominatorScale)) / denominator) *
|
|
115
|
+
(inverseScale / denominatorScale);
|
|
116
|
+
return Number.isFinite(re) && Number.isFinite(im) ? Complex.from(re, im) : undefined;
|
|
117
|
+
}
|
|
118
|
+
/** Copy and renormalize every sample; reject invalid/singular data without modifying the input. */
|
|
119
|
+
static renormalizeSamples(samples, fromOhms, toOhms) {
|
|
120
|
+
RfCalculations.validateReference(fromOhms);
|
|
121
|
+
RfCalculations.validateReference(toOhms);
|
|
122
|
+
return samples.map((sample, index) => {
|
|
123
|
+
if (!Number.isFinite(sample.frequencyHz) ||
|
|
124
|
+
sample.frequencyHz < 0 ||
|
|
125
|
+
sample.reflectionCoefficient.length !== 2) {
|
|
126
|
+
throw new RangeError(`Invalid sample at index ${index}.`);
|
|
127
|
+
}
|
|
128
|
+
const gamma = RfCalculations.renormalizeReflection(Complex.from(...sample.reflectionCoefficient), fromOhms, toOhms);
|
|
129
|
+
if (!gamma) {
|
|
130
|
+
throw new RangeError(`Renormalization is singular or outside the numeric range at sample ${index}.`);
|
|
131
|
+
}
|
|
132
|
+
return { frequencyHz: sample.frequencyHz, reflectionCoefficient: gamma.toVector() };
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Convert reactance in ohms at a frequency in Hz to an ideal series L or C.
|
|
137
|
+
* Zero frequency, zero reactance, or an unrepresentable component returns undefined.
|
|
138
|
+
* Non-finite reactance and negative/non-finite frequency throw RangeError.
|
|
139
|
+
*/
|
|
140
|
+
static reactanceToComponent(reactanceOhms, frequencyHz) {
|
|
141
|
+
if (!Number.isFinite(reactanceOhms)) {
|
|
142
|
+
throw new RangeError('Reactance must be finite.');
|
|
143
|
+
}
|
|
144
|
+
if (!Number.isFinite(frequencyHz) || frequencyHz < 0) {
|
|
145
|
+
throw new RangeError('Frequency must be finite and non-negative.');
|
|
146
|
+
}
|
|
147
|
+
if (frequencyHz === 0 || reactanceOhms === 0) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Compute in log space so intermediate products/quotients cannot overflow.
|
|
151
|
+
const logReactance = Math.log(Math.abs(reactanceOhms));
|
|
152
|
+
const logAngularFrequency = Math.log(2 * Math.PI) + Math.log(frequencyHz);
|
|
153
|
+
const value = Math.exp((reactanceOhms > 0 ? logReactance : -logReactance) - logAngularFrequency);
|
|
154
|
+
if (!Number.isFinite(value) || value === 0) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
return reactanceOhms > 0
|
|
158
|
+
? { kind: 'inductor', inductanceHenries: value }
|
|
159
|
+
: { kind: 'capacitor', capacitanceFarads: value };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Circle } from '
|
|
2
|
-
import {
|
|
3
|
-
import { Complex } from './complex/Complex.js';
|
|
1
|
+
import type { Circle, Point } from '../math/geometry.js';
|
|
2
|
+
import { Complex } from '../math/Complex.js';
|
|
4
3
|
export declare class SmithConstantCircle {
|
|
5
4
|
Z0: number;
|
|
6
5
|
constructor(Z0?: number);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Complex } from './complex/Complex.js';
|
|
1
|
+
import { Complex } from '../math/Complex.js';
|
|
3
2
|
export class SmithConstantCircle {
|
|
4
3
|
Z0;
|
|
5
4
|
constructor(Z0 = 50) {
|
|
@@ -18,8 +17,8 @@ export class SmithConstantCircle {
|
|
|
18
17
|
return this.transform(c, 1 - c.re, -c.im, 1 + c.re, c.im, -2);
|
|
19
18
|
}
|
|
20
19
|
transform(value, nr, ni, dr, di, determinant) {
|
|
21
|
-
const quotient =
|
|
22
|
-
if (!quotient) {
|
|
20
|
+
const quotient = Complex.div(Complex.from(nr, ni), Complex.from(dr, di));
|
|
21
|
+
if (!Number.isFinite(quotient.re) || !Number.isFinite(quotient.im)) {
|
|
23
22
|
return;
|
|
24
23
|
}
|
|
25
24
|
// The analytic imaginary numerator avoids cancellation of nearly equal products.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Complex } from '../math/Complex.js';
|
|
2
|
+
export interface PeripheralScale {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
unit: '°' | 'λ';
|
|
6
|
+
ticks: number[];
|
|
7
|
+
major: (value: number) => boolean;
|
|
8
|
+
angle: (value: number) => number;
|
|
9
|
+
read: (gamma: Complex) => number | null;
|
|
10
|
+
}
|
|
11
|
+
export declare class PeripheralScaleDefinitions {
|
|
12
|
+
private constructor();
|
|
13
|
+
private static phase;
|
|
14
|
+
/** A full reflection-coefficient rotation represents half a wavelength along the line. */
|
|
15
|
+
static create(): PeripheralScale[];
|
|
16
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export class PeripheralScaleDefinitions {
|
|
2
|
+
constructor() { }
|
|
3
|
+
static phase(gamma) {
|
|
4
|
+
return gamma.re === 0 && gamma.im === 0
|
|
5
|
+
? null
|
|
6
|
+
: (Math.atan2(gamma.im, gamma.re) * 180) / Math.PI;
|
|
7
|
+
}
|
|
8
|
+
/** A full reflection-coefficient rotation represents half a wavelength along the line. */
|
|
9
|
+
static create() {
|
|
10
|
+
const wavelengths = (gamma, direction) => {
|
|
11
|
+
const degrees = PeripheralScaleDefinitions.phase(gamma);
|
|
12
|
+
return degrees === null ? null : (0.25 + (direction * degrees) / 720 + 0.5) % 0.5;
|
|
13
|
+
};
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
id: 'transmission-phase',
|
|
17
|
+
title: 'Transmission phase · °',
|
|
18
|
+
unit: '°',
|
|
19
|
+
ticks: Array.from({ length: 179 }, (_, i) => -89 + i),
|
|
20
|
+
major: (v) => v % 5 === 0,
|
|
21
|
+
// Project from Γ = −1 to the perimeter, not from the chart center.
|
|
22
|
+
angle: (v) => 2 * v,
|
|
23
|
+
read: (gamma) => PeripheralScaleDefinitions.phase({ re: 1 + gamma.re, im: gamma.im }),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 'reflection-phase',
|
|
27
|
+
title: 'Reflection phase · °',
|
|
28
|
+
unit: '°',
|
|
29
|
+
ticks: Array.from({ length: 180 }, (_, i) => -178 + i * 2),
|
|
30
|
+
major: (v) => v % 10 === 0,
|
|
31
|
+
angle: (v) => v,
|
|
32
|
+
read: PeripheralScaleDefinitions.phase,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'wavelengths-load',
|
|
36
|
+
title: 'Wavelengths → load',
|
|
37
|
+
unit: 'λ',
|
|
38
|
+
ticks: Array.from({ length: 250 }, (_, i) => i / 500),
|
|
39
|
+
major: (v) => Math.round(v * 500) % 5 === 0,
|
|
40
|
+
angle: (v) => 720 * v - 180,
|
|
41
|
+
read: (gamma) => wavelengths(gamma, 1),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'wavelengths-generator',
|
|
45
|
+
title: 'Wavelengths → generator',
|
|
46
|
+
unit: 'λ',
|
|
47
|
+
ticks: Array.from({ length: 250 }, (_, i) => i / 500),
|
|
48
|
+
major: (v) => Math.round(v * 500) % 5 === 0,
|
|
49
|
+
angle: (v) => 180 - 720 * v,
|
|
50
|
+
read: (gamma) => wavelengths(gamma, -1),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Complex } from '../math/Complex.js';
|
|
2
|
+
export interface RadialScale {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
unit: 'dB' | 'ratio';
|
|
7
|
+
read: (gamma: Complex) => number;
|
|
8
|
+
values: number[];
|
|
9
|
+
position: (value: number) => number;
|
|
10
|
+
}
|
|
11
|
+
export declare class RadialScaleDefinitions {
|
|
12
|
+
private constructor();
|
|
13
|
+
/** Normalized positions along each scale, from zero to one. */
|
|
14
|
+
static create(): RadialScale[];
|
|
15
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { SmithConstantCircle } from '../rf/SmithConstantCircle.js';
|
|
2
|
+
export class RadialScaleDefinitions {
|
|
3
|
+
constructor() { }
|
|
4
|
+
/** Normalized positions along each scale, from zero to one. */
|
|
5
|
+
static create() {
|
|
6
|
+
const calcs = new SmithConstantCircle();
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
id: 'vswr',
|
|
10
|
+
unit: 'ratio',
|
|
11
|
+
read: (gamma) => calcs.rflCoeffToSwr(gamma),
|
|
12
|
+
title: 'VSWR',
|
|
13
|
+
values: [1, 1.5, 2, 3, 5, 10, Infinity],
|
|
14
|
+
position: (v) => (v === Infinity ? 1 : calcs.swrToRflCoeffEOrI(v)),
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'vswr-db',
|
|
18
|
+
unit: 'dB',
|
|
19
|
+
read: (gamma) => calcs.rflCoeffToDBS(gamma),
|
|
20
|
+
title: 'Standing-wave ratio · dB',
|
|
21
|
+
values: [0, 3, 6, 10, 15, 20, Infinity],
|
|
22
|
+
position: (v) => (v === Infinity ? 1 : calcs.dBSToAbsRflCoeff(v)),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'return-loss',
|
|
26
|
+
unit: 'dB',
|
|
27
|
+
read: (gamma) => calcs.rflCoeffToReturnLoss(gamma),
|
|
28
|
+
title: 'Return loss · dB',
|
|
29
|
+
values: [Infinity, 20, 14, 10, 6, 3, 0],
|
|
30
|
+
position: (v) => calcs.returnLossToRflCoeffEOrI(v),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 'mismatch-loss',
|
|
34
|
+
unit: 'dB',
|
|
35
|
+
read: (gamma) => calcs.rflCoeffToMismatchLoss(gamma),
|
|
36
|
+
title: 'Reflection loss · dB',
|
|
37
|
+
description: 'Reflection loss (mismatch loss): −10 log10(1 − |Γ|²), in dB.',
|
|
38
|
+
values: [0, 0.1, 0.5, 1, 2, 4, Infinity],
|
|
39
|
+
position: (v) => calcs.mismatchLossToRflCoeffEOrI(v),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'reflected-power',
|
|
43
|
+
unit: 'ratio',
|
|
44
|
+
read: (gamma) => calcs.rflCoeffP(gamma),
|
|
45
|
+
title: 'Power reflection coefficient',
|
|
46
|
+
description: 'Reflected power divided by incident power: |Γ|² (dimensionless).',
|
|
47
|
+
values: [0, 0.01, 0.1, 0.25, 0.5, 0.75, 1],
|
|
48
|
+
position: (v) => calcs.rflCoeffPToEOrI(v),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'transmitted-power',
|
|
52
|
+
unit: 'ratio',
|
|
53
|
+
read: (gamma) => calcs.rflCoeffToTransmCoeffP(gamma),
|
|
54
|
+
title: 'Power transmission coefficient',
|
|
55
|
+
description: 'Net power delivered to the load divided by incident power: 1 − |Γ|² (dimensionless).',
|
|
56
|
+
values: [1, 0.99, 0.9, 0.75, 0.5, 0.25, 0],
|
|
57
|
+
position: (v) => calcs.transmCoeffPToRflCoeffEOrI(v),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'standing-wave-loss',
|
|
61
|
+
unit: 'ratio',
|
|
62
|
+
read: (gamma) => calcs.rflCoeffToSwLossCoeff(gamma),
|
|
63
|
+
title: 'Standing-wave loss coefficient',
|
|
64
|
+
values: [1, 1.1, 1.5, 2, 3, 5, Infinity],
|
|
65
|
+
position: (v) => (v === Infinity ? 1 : calcs.swLossCoeffToRflCoeffEOrI(v)),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'standing-wave-peak',
|
|
69
|
+
unit: 'ratio',
|
|
70
|
+
read: (gamma) => calcs.rflCoeffToSwPeakConstP(gamma),
|
|
71
|
+
title: 'Standing-wave peak · constant power',
|
|
72
|
+
values: [1, 1.2, 1.5, 2, 3, Infinity],
|
|
73
|
+
position: (v) => (v === Infinity ? 1 : calcs.swPeakConstPToRflCoeffEOrI(v)),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'reflection-coefficient',
|
|
77
|
+
unit: 'ratio',
|
|
78
|
+
read: (gamma) => calcs.rflCoeffEOrI(gamma),
|
|
79
|
+
title: 'Reflection coefficient · |Γ|',
|
|
80
|
+
values: [0, 0.2, 0.4, 0.6, 0.8, 1],
|
|
81
|
+
position: (v) => v,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 'attenuation',
|
|
85
|
+
unit: 'dB',
|
|
86
|
+
read: (gamma) => calcs.rflCoeffToAttenuation(gamma),
|
|
87
|
+
title: 'Attenuation · dB',
|
|
88
|
+
description: 'One-way attenuation of a matched line or attenuator terminated in an open or short circuit. Not insertion loss of an arbitrary load.',
|
|
89
|
+
values: [Infinity, 10, 7, 5, 3, 1, 0],
|
|
90
|
+
position: (v) => calcs.attenuationToRflCoeff(v),
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'voltage-transmission',
|
|
94
|
+
unit: 'ratio',
|
|
95
|
+
read: (gamma) => calcs.rflCoeffToTransmCoeffEOrI(gamma),
|
|
96
|
+
title: 'Voltage transmission coefficient',
|
|
97
|
+
description: 'Voltage transmission magnitude: |1 + Γ| (dimensionless).',
|
|
98
|
+
values: [0, 0.4, 0.8, 1.2, 1.6, 2],
|
|
99
|
+
position: (v) => v / 2,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'current-transmission',
|
|
103
|
+
unit: 'ratio',
|
|
104
|
+
read: (gamma) => calcs.rflCoeffToCurrentTransmission(gamma),
|
|
105
|
+
title: 'Current transmission coefficient',
|
|
106
|
+
description: 'Current transmission magnitude: |1 − Γ|, using the voltage reflection coefficient Γ (dimensionless).',
|
|
107
|
+
values: [0, 0.4, 0.8, 1.2, 1.6, 2],
|
|
108
|
+
position: (v) => v / 2,
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type { Complex } from '../
|
|
2
|
-
import { SmithGroup } from '../
|
|
1
|
+
import type { Complex } from '../math/Complex.js';
|
|
2
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
3
3
|
/** Peripheral rulers in the chart's 500-unit coordinate system. */
|
|
4
4
|
export declare class SmithPeripheralScales extends SmithGroup {
|
|
5
|
+
private static point;
|
|
6
|
+
private static rulerRadius;
|
|
7
|
+
readonly labels: SmithGroup;
|
|
5
8
|
private readonly scales;
|
|
6
9
|
private readonly axes;
|
|
7
10
|
constructor();
|
|
11
|
+
show(): SmithGroup;
|
|
12
|
+
hide(): SmithGroup;
|
|
8
13
|
/** Connect to the same cursor or marker data as the independent parameter scales. */
|
|
9
14
|
update(gamma: Complex | null): void;
|
|
10
15
|
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { select, format } from 'd3';
|
|
2
|
-
import { SmithGroup } from '../
|
|
3
|
-
import {
|
|
2
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
3
|
+
import { PeripheralScaleDefinitions } from './PeripheralScaleDefinitions.js';
|
|
4
4
|
let nextScaleId = 0;
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
function point(radius, degrees) {
|
|
8
|
-
const angle = (degrees * Math.PI) / 180;
|
|
9
|
-
return [250 + radius * Math.cos(angle), 250 - radius * Math.sin(angle)];
|
|
10
|
-
}
|
|
5
|
+
const chartRadius = 250;
|
|
6
|
+
const groupWidth = 40;
|
|
11
7
|
/** Peripheral rulers in the chart's 500-unit coordinate system. */
|
|
12
8
|
export class SmithPeripheralScales extends SmithGroup {
|
|
13
|
-
|
|
9
|
+
static point(radius, degrees) {
|
|
10
|
+
const angle = (degrees * Math.PI) / 180;
|
|
11
|
+
return [250 + radius * Math.cos(angle), 250 - radius * Math.sin(angle)];
|
|
12
|
+
}
|
|
13
|
+
static rulerRadius(index) {
|
|
14
|
+
return chartRadius + groupWidth / 2 + Math.floor(index / 2) * groupWidth;
|
|
15
|
+
}
|
|
16
|
+
labels = new SmithGroup()
|
|
17
|
+
.attr('data-label-layer', 'peripheral-scales')
|
|
18
|
+
.attr('pointer-events', 'none');
|
|
19
|
+
scales = PeripheralScaleDefinitions.create();
|
|
14
20
|
axes = this.Element.attr('data-layer', 'peripheral-scales')
|
|
15
21
|
.attr('pointer-events', 'none')
|
|
16
22
|
.selectAll('g')
|
|
@@ -21,25 +27,48 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
21
27
|
.attr('aria-label', (scale) => scale.title);
|
|
22
28
|
constructor() {
|
|
23
29
|
super();
|
|
30
|
+
const labelAxes = this.labels.Element.selectAll('g')
|
|
31
|
+
.data(this.scales)
|
|
32
|
+
.join('g')
|
|
33
|
+
.attr('data-label-scale', (scale) => scale.id)
|
|
34
|
+
.nodes();
|
|
35
|
+
// Two paired rulers: transmission/reflection phase, then electrical length
|
|
36
|
+
// toward load/generator. Strong boundaries enclose each pair.
|
|
37
|
+
this.Element.selectAll('circle.peripheral-boundary')
|
|
38
|
+
.data([chartRadius, chartRadius + groupWidth, chartRadius + 2 * groupWidth])
|
|
39
|
+
.join('circle')
|
|
40
|
+
.attr('class', 'peripheral-boundary')
|
|
41
|
+
.attr('cx', 250)
|
|
42
|
+
.attr('cy', 250)
|
|
43
|
+
.attr('r', (radius) => radius)
|
|
44
|
+
.attr('fill', 'none')
|
|
45
|
+
.attr('stroke', '#334155')
|
|
46
|
+
.attr('stroke-width', 1.1)
|
|
47
|
+
.attr('vector-effect', 'non-scaling-stroke');
|
|
24
48
|
this.axes.each(function (scale, index) {
|
|
49
|
+
const labelAxis = select(labelAxes[index]);
|
|
25
50
|
const axis = select(this);
|
|
26
|
-
const radius =
|
|
51
|
+
const radius = SmithPeripheralScales.rulerRadius(index);
|
|
52
|
+
const side = index % 2 === 0 ? -1 : 1;
|
|
27
53
|
const captionAngle = scale.unit === 'λ' ? 180 : 0;
|
|
28
54
|
axis.append('title').text(scale.title);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
if (index % 2 === 0) {
|
|
56
|
+
axis
|
|
57
|
+
.append('circle')
|
|
58
|
+
.attr('class', 'peripheral-ruler')
|
|
59
|
+
.attr('cx', 250)
|
|
60
|
+
.attr('cy', 250)
|
|
61
|
+
.attr('r', radius)
|
|
62
|
+
.attr('fill', 'none')
|
|
63
|
+
.attr('stroke', '#475569')
|
|
64
|
+
.attr('stroke-width', 0.6)
|
|
65
|
+
.attr('vector-effect', 'non-scaling-stroke');
|
|
66
|
+
}
|
|
38
67
|
for (const value of scale.ticks) {
|
|
39
68
|
const angle = scale.angle(value);
|
|
40
|
-
const [x1, y1] = point(radius, angle);
|
|
69
|
+
const [x1, y1] = SmithPeripheralScales.point(radius, angle);
|
|
41
70
|
const major = scale.major(value);
|
|
42
|
-
const [x2, y2] = point(radius
|
|
71
|
+
const [x2, y2] = SmithPeripheralScales.point(radius + side * (major ? 4 : 2), angle);
|
|
43
72
|
axis
|
|
44
73
|
.append('line')
|
|
45
74
|
.attr('x1', x1)
|
|
@@ -51,9 +80,9 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
51
80
|
.attr('vector-effect', 'non-scaling-stroke');
|
|
52
81
|
const captionDistance = Math.abs(((angle - captionAngle + 540) % 360) - 180);
|
|
53
82
|
if (major && captionDistance > 25) {
|
|
54
|
-
const [x, y] = point(radius +
|
|
83
|
+
const [x, y] = SmithPeripheralScales.point(radius + side * 11, angle);
|
|
55
84
|
const rotation = angle >= 0 ? 90 - angle : -90 - angle;
|
|
56
|
-
|
|
85
|
+
labelAxis
|
|
57
86
|
.append('text')
|
|
58
87
|
.attr('x', x)
|
|
59
88
|
.attr('y', y)
|
|
@@ -67,9 +96,9 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
67
96
|
}
|
|
68
97
|
}
|
|
69
98
|
// Reserve a label sector for the curved caption without masking the ruler or its ticks.
|
|
70
|
-
const captionRadius = radius + 5;
|
|
71
|
-
const start = point(captionRadius, captionAngle + 45);
|
|
72
|
-
const end = point(captionRadius, captionAngle - 45);
|
|
99
|
+
const captionRadius = radius + (side < 0 ? -15 : 5);
|
|
100
|
+
const start = SmithPeripheralScales.point(captionRadius, captionAngle + 45);
|
|
101
|
+
const end = SmithPeripheralScales.point(captionRadius, captionAngle - 45);
|
|
73
102
|
const pathId = `smithkit-peripheral-caption-${nextScaleId++}`;
|
|
74
103
|
axis
|
|
75
104
|
.append('defs')
|
|
@@ -81,7 +110,7 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
81
110
|
? 'WAVELENGTHS TOWARD GENERATOR →'
|
|
82
111
|
: '← WAVELENGTHS TOWARD LOAD'
|
|
83
112
|
: scale.title.toUpperCase();
|
|
84
|
-
|
|
113
|
+
labelAxis
|
|
85
114
|
.append('text')
|
|
86
115
|
.attr('class', 'peripheral-caption')
|
|
87
116
|
.attr('text-anchor', 'middle')
|
|
@@ -104,6 +133,14 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
104
133
|
.attr('stroke-width', 1);
|
|
105
134
|
});
|
|
106
135
|
}
|
|
136
|
+
show() {
|
|
137
|
+
this.labels.show();
|
|
138
|
+
return super.show();
|
|
139
|
+
}
|
|
140
|
+
hide() {
|
|
141
|
+
this.labels.hide();
|
|
142
|
+
return super.hide();
|
|
143
|
+
}
|
|
107
144
|
/** Connect to the same cursor or marker data as the independent parameter scales. */
|
|
108
145
|
update(gamma) {
|
|
109
146
|
const valid = gamma !== null && Number.isFinite(gamma.abs()) && gamma.abs() <= 1;
|
|
@@ -117,7 +154,7 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
117
154
|
dot.attr('visibility', 'hidden').attr('data-value', null);
|
|
118
155
|
return;
|
|
119
156
|
}
|
|
120
|
-
const [x, y] = point(
|
|
157
|
+
const [x, y] = SmithPeripheralScales.point(SmithPeripheralScales.rulerRadius(index), scale.angle(value));
|
|
121
158
|
dot.attr('cx', x).attr('cy', y).attr('data-value', value).attr('visibility', null);
|
|
122
159
|
});
|
|
123
160
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Complex } from '../
|
|
1
|
+
import type { Complex } from '../math/Complex.js';
|
|
2
2
|
/** Independent parameter scales. Connect update() to a chart's cursor events. */
|
|
3
3
|
export declare class SmithScales {
|
|
4
4
|
private readonly scales;
|
|
@@ -11,6 +11,8 @@ export declare class SmithScales {
|
|
|
11
11
|
draw(target: string | HTMLElement): void;
|
|
12
12
|
/** Show a passive-load reflection coefficient, or hide indicators with null. */
|
|
13
13
|
update(gamma: Complex | null): void;
|
|
14
|
+
/** Export all mounted scales in their current layout as a standalone SVG. */
|
|
15
|
+
toSvg(): string;
|
|
14
16
|
destroy(): void;
|
|
15
17
|
private assertAlive;
|
|
16
18
|
}
|