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
package/README.md
CHANGED
|
@@ -5,44 +5,35 @@ interactive SVG Smith charts, RF calculations, and S11 measurement exploration.
|
|
|
5
5
|
|
|
6
6
|
[Try the interactive demo](https://rosek86.github.io/smithkit/).
|
|
7
7
|
|
|
8
|
+
Upgrading from 0.1.x? Version 0.2.0 groups calculation, parsing, formatting, and
|
|
9
|
+
comparison functions into classes. See the [migration guide](https://github.com/rosek86/smithkit/blob/v0.2.0/docs/migration-0.2.md)
|
|
10
|
+
for the changed imports.
|
|
11
|
+
|
|
8
12
|
## Features
|
|
9
13
|
|
|
10
14
|
- Labeled resistance, reactance, conductance, and susceptance grids.
|
|
11
15
|
- Configurable constant-Q and constant-VSWR circles.
|
|
12
16
|
- Zoom, pan, view reset, and cursor readings.
|
|
13
|
-
- Named traces with colors, visibility, and
|
|
17
|
+
- Named traces with colors, visibility, and keyboard/touch/mouse markers that snap to samples.
|
|
14
18
|
- Marker comparisons: frequency, complex impedance, and wrapped phase differences.
|
|
15
19
|
- Physical impedance/admittance conversions and DOM-independent RF readings.
|
|
16
20
|
- Twelve parameter scales mounted independently of chart zoom.
|
|
17
21
|
- Four peripheral rulers for phase and electrical length.
|
|
18
22
|
- One-port Touchstone 1.x import with RI, MA, and DB representations.
|
|
23
|
+
- Standalone SVG export of the current chart and radial scales.
|
|
19
24
|
- ESM modules and TypeScript declarations.
|
|
20
25
|
|
|
21
26
|
## Installation
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```sh
|
|
26
|
-
npm install smithkit@0.1.0
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Until publication, build and install an archive from source:
|
|
28
|
+
Install from npm:
|
|
30
29
|
|
|
31
30
|
```sh
|
|
32
|
-
|
|
33
|
-
cd smithkit
|
|
34
|
-
npm ci
|
|
35
|
-
npm pack
|
|
31
|
+
npm install smithkit
|
|
36
32
|
```
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
npm install /path/to/smithkit/smithkit-0.1.0.tgz
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Building requires Node.js 24 or later. Browser applications need SVG, ES2022,
|
|
45
|
-
and an ESM-compatible build tool. No library stylesheet is required.
|
|
34
|
+
Browser applications need SVG, ES2022, and an ESM-compatible build tool.
|
|
35
|
+
No library stylesheet is required. To build the library from source, see
|
|
36
|
+
[Contributing](https://github.com/rosek86/smithkit/blob/main/CONTRIBUTING.md).
|
|
46
37
|
|
|
47
38
|
For a complete application using the installed package, see the
|
|
48
39
|
[standalone integration example](https://github.com/rosek86/smithkit/tree/main/examples/basic).
|
|
@@ -77,11 +68,11 @@ must be finite and non-negative; both coordinates must be finite. A trace must
|
|
|
77
68
|
contain at least one sample.
|
|
78
69
|
|
|
79
70
|
Each new trace receives one marker on its first sample. Drag markers to select
|
|
80
|
-
samples, scroll to zoom, and drag the chart to pan. Markers
|
|
81
|
-
points. `chart.resetView()` restores the initial view, including peripheral rulers.
|
|
71
|
+
samples with a mouse or touch, scroll to zoom, and drag the chart to pan. Markers
|
|
72
|
+
and their focus indicators stay above grid labels and sample points. `chart.resetView()` restores the initial view, including peripheral rulers.
|
|
82
73
|
|
|
83
74
|
Construct `Smith` only in a browser, such as your framework's mount hook. Importing
|
|
84
|
-
the package and using its calculation or parsing
|
|
75
|
+
the package and using its calculation or parsing methods does not require a DOM.
|
|
85
76
|
|
|
86
77
|
Zoom is enabled by default. For a fixed view, call `chart.setZoomEnabled(false)` before or after mounting.
|
|
87
78
|
It disables wheel/double-click zoom and mouse/touch panning and pinch zoom while
|
|
@@ -103,6 +94,25 @@ chart.draw('#smith');
|
|
|
103
94
|
container throws. Call `chart.destroy()` on unmount; it removes the SVG, releases
|
|
104
95
|
event handlers, and cancels queued notifications. Repeated destruction is safe.
|
|
105
96
|
|
|
97
|
+
### Keyboard and touch markers
|
|
98
|
+
|
|
99
|
+
Use Tab/Shift+Tab to focus a marker. Arrow keys move through samples in input order;
|
|
100
|
+
Right/Up advances and Left/Down goes back. Shift+Arrow or Page Up/Down moves ten
|
|
101
|
+
samples, and Home/End selects the first/last sample. Navigation clamps at the ends
|
|
102
|
+
and also works when chart zoom is disabled. A single-sample trace remains focusable
|
|
103
|
+
for reading, with its slider marked disabled.
|
|
104
|
+
|
|
105
|
+
A focused marker has a contrasting outline and exposes its trace name, marker
|
|
106
|
+
number, sample position, and frequency to assistive technology. Hidden traces are
|
|
107
|
+
excluded from keyboard focus. `chart.focusMarker(id)` allows a separate marker
|
|
108
|
+
selector to focus the matching chart control. The demo provides a **Focus on chart**
|
|
109
|
+
button beside its marker selector.
|
|
110
|
+
|
|
111
|
+
Markers have a 44 CSS px circular hit area and an 18 CSS px triangle, kept constant
|
|
112
|
+
through zoom and container resizing. A marker touch gesture does not pan the chart;
|
|
113
|
+
cancelling it releases the drag state. Touch target areas may overlap for nearby
|
|
114
|
+
markers; use keyboard focus or the demo selector to reach an obscured marker.
|
|
115
|
+
|
|
106
116
|
## Traces and markers
|
|
107
117
|
|
|
108
118
|
Trace and marker IDs are opaque strings, unique within a chart and never reused
|
|
@@ -135,6 +145,7 @@ chart.removeMarker(markerB);
|
|
|
135
145
|
| `clearTraces()` | Removes all traces and their markers. |
|
|
136
146
|
| `addMarker(traceId, sampleIndex = 0)` | Returns a marker ID, or `undefined` if the trace is missing. |
|
|
137
147
|
| `getMarker(id)` | Returns a `MarkerSnapshot`, or `undefined` if missing. |
|
|
148
|
+
| `focusMarker(id)` | Moves keyboard focus to a mounted, visible marker; returns `false` if missing or not focusable. |
|
|
138
149
|
| `setMarkerSample(id, sampleIndex)` | Selects an existing sample and queues a marker notification. |
|
|
139
150
|
| `removeMarker(id)` | Removes one marker without renumbering the remaining markers. |
|
|
140
151
|
| `compareMarkers(a, b)` | Returns B − A, or `undefined` if either marker is missing. |
|
|
@@ -206,7 +217,7 @@ const unsubscribe = chart.onEvent((event) => {
|
|
|
206
217
|
console.log(event.data?.impedanceOhms?.toVector());
|
|
207
218
|
return;
|
|
208
219
|
}
|
|
209
|
-
// Marker, MarkerDragStart, and MarkerDragEnd
|
|
220
|
+
// Marker, MarkerSelect, MarkerDragStart, and MarkerDragEnd carry a MarkerSnapshot.
|
|
210
221
|
console.log(event.data.markerId, event.data.frequencyHz);
|
|
211
222
|
});
|
|
212
223
|
|
|
@@ -216,7 +227,12 @@ chart.destroy();
|
|
|
216
227
|
```
|
|
217
228
|
|
|
218
229
|
The event types are `Cursor` (`'cursor'`), `Marker` (`'marker'`),
|
|
230
|
+
`MarkerSelect` (`'marker-select'`),
|
|
219
231
|
`MarkerDragStart` (`'marker-drag-start'`), and `MarkerDragEnd` (`'marker-drag-end'`).
|
|
232
|
+
`MarkerSelect` fires synchronously when a marker receives focus or is engaged by
|
|
233
|
+
keyboard navigation or a pointer press. Use it to select the corresponding
|
|
234
|
+
readout; it does not indicate a position change. Keyboard changes use the normal
|
|
235
|
+
queued `Marker` event and do not emit drag lifecycle events.
|
|
220
236
|
Cursor movement is suspended during marker dragging. Drag start/end events fire
|
|
221
237
|
synchronously; marker position notifications are queued and report the latest
|
|
222
238
|
snapshot at delivery. Before delivery, repeated updates to the same marker coalesce
|
|
@@ -227,7 +243,7 @@ Trace metadata changes do not emit marker events; refresh metadata after mutatio
|
|
|
227
243
|
Destruction suppresses application callbacks.
|
|
228
244
|
|
|
229
245
|
`chart.cursorReading` returns the last cursor position. Cursor and marker readings
|
|
230
|
-
share `SmithReading`; `readReflection(gamma, referenceImpedanceOhms = 50)` produces
|
|
246
|
+
share `SmithReading`; `RfCalculations.readReflection(gamma, referenceImpedanceOhms = 50)` produces
|
|
231
247
|
the same reading without constructing a chart.
|
|
232
248
|
|
|
233
249
|
| Fields | Units / meaning |
|
|
@@ -253,7 +269,7 @@ infinite scalar limit is preserved: perfect match gives infinite return loss;
|
|
|
253
269
|
For active loads (\|Γ\| > 1), VSWR, standing-wave quantities, reflection loss,
|
|
254
270
|
attenuation, and power transmission are `undefined`. Other quantities remain
|
|
255
271
|
available. Non-finite complex inputs or invalid reference impedances throw
|
|
256
|
-
`RangeError` in the public RF
|
|
272
|
+
`RangeError` in the public RF methods. Unrepresentable complex conversion
|
|
257
273
|
results are `undefined`.
|
|
258
274
|
|
|
259
275
|
## Selecting a marker by frequency
|
|
@@ -273,22 +289,22 @@ measurement frequency; dragging and sample selection keep that field synchronize
|
|
|
273
289
|
## Calculations without a chart
|
|
274
290
|
|
|
275
291
|
```ts
|
|
276
|
-
import { Complex,
|
|
292
|
+
import { Complex, RfCalculations } from 'smithkit';
|
|
277
293
|
|
|
278
|
-
const gamma = impedanceToReflection(Complex.from(75, 25), 50)!;
|
|
279
|
-
const reading = readReflection(gamma, 50);
|
|
294
|
+
const gamma = RfCalculations.impedanceToReflection(Complex.from(75, 25), 50)!;
|
|
295
|
+
const reading = RfCalculations.readReflection(gamma, 50);
|
|
280
296
|
console.log(reading.impedanceOhms?.toVector()); // Approximately [75, 25].
|
|
281
297
|
console.log(reading.admittanceSiemens?.toVector());
|
|
282
298
|
```
|
|
283
299
|
|
|
284
|
-
|
|
|
285
|
-
|
|
|
286
|
-
| `reflectionToImpedance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Z in Ω. |
|
|
287
|
-
| `impedanceToReflection(impedanceOhms, referenceImpedanceOhms = 50)` | Physical Z in Ω → Γ. |
|
|
288
|
-
| `reflectionToAdmittance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Y in S. |
|
|
289
|
-
| `admittanceToReflection(admittanceSiemens, referenceImpedanceOhms = 50)` | Physical Y in S → Γ. |
|
|
290
|
-
| `readReflection(gamma, referenceImpedanceOhms = 50)` | Complete `SmithReading`. |
|
|
291
|
-
| `
|
|
300
|
+
| Static method | Input and output |
|
|
301
|
+
| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
302
|
+
| `RfCalculations.reflectionToImpedance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Z in Ω. |
|
|
303
|
+
| `RfCalculations.impedanceToReflection(impedanceOhms, referenceImpedanceOhms = 50)` | Physical Z in Ω → Γ. |
|
|
304
|
+
| `RfCalculations.reflectionToAdmittance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Y in S. |
|
|
305
|
+
| `RfCalculations.admittanceToReflection(admittanceSiemens, referenceImpedanceOhms = 50)` | Physical Y in S → Γ. |
|
|
306
|
+
| `RfCalculations.readReflection(gamma, referenceImpedanceOhms = 50)` | Complete `SmithReading`. |
|
|
307
|
+
| `MarkerMeasurements.compare(a, b)` | Compare readings without a chart. Each input needs `frequencyHz`, `reflectionCoefficient`, and `impedanceOhms`. |
|
|
292
308
|
|
|
293
309
|
Comparison results contain `frequencyDeltaHz`, `impedanceDeltaOhms`, and
|
|
294
310
|
`phaseDeltaDegrees`. Phase differences use B − A wrapped to **[−180°, 180°)**:
|
|
@@ -299,27 +315,27 @@ a point comparison, not sweep phase unwrapping or group delay.
|
|
|
299
315
|
|
|
300
316
|
`Complex.from(re, im)` constructs complex numbers. Read components through `re` and `im`. Arithmetic (`add`, `sub`,
|
|
301
317
|
`mul`, `div`, `pow`) returns new values. The class also provides `abs`, `arg`
|
|
302
|
-
(radians), and static
|
|
318
|
+
(radians), and static methods such as `Complex.conj`, `Complex.sqrt`,
|
|
303
319
|
`Complex.exp`, `Complex.log`, and trigonometric/hyperbolic functions and inverses. `toVector()` returns `[real, imaginary]`; `toString(dp)` formats
|
|
304
320
|
a Cartesian value. See the exported declarations for all operations.
|
|
305
321
|
|
|
306
|
-
|
|
307
|
-
digits and SI prefixes), `
|
|
308
|
-
`
|
|
322
|
+
The `SmithFormatter` class provides static methods: `SmithFormatter.number(value)` (three significant
|
|
323
|
+
digits and SI prefixes), `SmithFormatter.complex(value, unit?, decimalPlaces?)`, and
|
|
324
|
+
`SmithFormatter.polar(value, unit?, decimalPlaces?)` (phase in degrees). They work
|
|
309
325
|
without a chart or DOM. Complex formatters default to three fractional digits.
|
|
310
|
-
`
|
|
326
|
+
`SmithFormatter.number` includes spacing so you can append a unit, e.g. `SmithFormatter.number(1e9) + 'Hz'`.
|
|
311
327
|
|
|
312
|
-
`reactanceToComponent(reactanceOhms, frequencyHz)` calculates an ideal equivalent
|
|
328
|
+
`RfCalculations.reactanceToComponent(reactanceOhms, frequencyHz)` calculates an ideal equivalent
|
|
313
329
|
series component without formatting or constructing a chart:
|
|
314
330
|
|
|
315
331
|
```ts
|
|
316
|
-
import {
|
|
332
|
+
import { RfCalculations, SmithFormatter } from 'smithkit';
|
|
317
333
|
|
|
318
|
-
const component = reactanceToComponent(-50, 1e9);
|
|
334
|
+
const component = RfCalculations.reactanceToComponent(-50, 1e9);
|
|
319
335
|
if (component?.kind === 'capacitor') {
|
|
320
|
-
console.log(
|
|
336
|
+
console.log(SmithFormatter.number(component.capacitanceFarads) + 'F'); // 3.18 pF
|
|
321
337
|
} else if (component?.kind === 'inductor') {
|
|
322
|
-
console.log(
|
|
338
|
+
console.log(SmithFormatter.number(component.inductanceHenries) + 'H');
|
|
323
339
|
}
|
|
324
340
|
```
|
|
325
341
|
|
|
@@ -347,9 +363,10 @@ chart.layers.vswr.setVisible(true);
|
|
|
347
363
|
The four grid layers support `setVisible`, `setMinorVisible`, and
|
|
348
364
|
`setStyle(Partial<GridStyle>)`. Style fields: `stroke`, `majorWidth`, `minorWidth`,
|
|
349
365
|
`textColor`, `textFontFamily`, `textFontSize`. Widths are positive finite numbers
|
|
350
|
-
in CSS pixels. Font size is a positive finite
|
|
351
|
-
|
|
352
|
-
|
|
366
|
+
in CSS pixels. Font size is a positive finite base size in chart units; adaptive
|
|
367
|
+
layout raises it when needed to keep the font size at least 9 CSS pixels in the
|
|
368
|
+
default view. Partial updates retain other settings. Invalid numeric styles throw
|
|
369
|
+
before any property is changed.
|
|
353
370
|
|
|
354
371
|
`layers.q` and `layers.vswr` support `setVisible`,
|
|
355
372
|
`setStyle({ stroke?, strokeWidth? })`, `addValue`, and `removeValue`.
|
|
@@ -359,8 +376,23 @@ Duplicate additions and removal of absent values have no effect.
|
|
|
359
376
|
|
|
360
377
|
Grid labels use normalized values; readings use physical units. Strokes default
|
|
361
378
|
to slate gray with 1 px major and 0.6 px minor lines. Stroke widths stay constant
|
|
362
|
-
under zoom
|
|
363
|
-
|
|
379
|
+
under zoom. Layer controls do not expose drawing objects or SVG nodes.
|
|
380
|
+
|
|
381
|
+
Grid labels adapt automatically to the chart's rendered size,
|
|
382
|
+
including static charts with zoom disabled. The layout prioritizes key values,
|
|
383
|
+
hides labels that overlap or extend beyond the default view, and prioritizes zero
|
|
384
|
+
and the highest labeled axis value. It recalculates on resize and layer visibility
|
|
385
|
+
or style changes. Zoom and pan preserve the chosen labels and scale them smoothly
|
|
386
|
+
with the grid. This changes only labels; grid lines and ticks remain unchanged.
|
|
387
|
+
SVG exports preserve the current label layout.
|
|
388
|
+
|
|
389
|
+
For small static charts, hide minor grid lines and, when unnecessary, peripheral
|
|
390
|
+
scales using the controls above. Very small charts necessarily show fewer values;
|
|
391
|
+
use a larger container for detailed readings. Peripheral labels retain their full
|
|
392
|
+
wording and scale with the chart. Their rulers form two outlined bands: phase
|
|
393
|
+
(transmission/reflection) and electrical length (toward load/generator), with a
|
|
394
|
+
shared tick circle inside each band.
|
|
395
|
+
The independent `SmithScales` panel uses its own responsive layout.
|
|
364
396
|
|
|
365
397
|
## Parameter scales
|
|
366
398
|
|
|
@@ -418,12 +450,12 @@ result rejects the operation without changing Z₀ or data. Active marker drags
|
|
|
418
450
|
cursor indicators are cleared, and marker readings are queued with the new values.
|
|
419
451
|
Changing to the current Z₀ has no effect. Mutations after destruction throw.
|
|
420
452
|
|
|
421
|
-
Two DOM-independent
|
|
453
|
+
Two DOM-independent methods are available on `RfCalculations`:
|
|
422
454
|
|
|
423
|
-
- `renormalizeReflection(gamma, fromOhms, toOhms)` returns the new complex Γ or
|
|
455
|
+
- `RfCalculations.renormalizeReflection(gamma, fromOhms, toOhms)` returns the new complex Γ or
|
|
424
456
|
`undefined` for a singular/unrepresentable result. Exact open and short limits
|
|
425
457
|
remain Γ = +1 and −1. References must be positive, finite, real ohm values.
|
|
426
|
-
- `renormalizeSamples(samples, fromOhms, toOhms)` returns a new sample array in
|
|
458
|
+
- `RfCalculations.renormalizeSamples(samples, fromOhms, toOhms)` returns a new sample array in
|
|
427
459
|
the same order, preserving frequencies. Invalid samples or a singular result
|
|
428
460
|
throw `RangeError`; the input is never modified.
|
|
429
461
|
|
|
@@ -438,15 +470,15 @@ multiport renormalization are outside the supported scope.
|
|
|
438
470
|
|
|
439
471
|
## Touchstone import
|
|
440
472
|
|
|
441
|
-
`
|
|
473
|
+
`Touchstone.parse(text)` returns `{ samples, referenceImpedanceOhms }`. It accepts
|
|
442
474
|
one-port Touchstone 1.x, converts RI/MA/DB into Cartesian Γ and all frequencies
|
|
443
475
|
into Hz, and throws for unsupported or invalid input.
|
|
444
476
|
|
|
445
477
|
```ts
|
|
446
|
-
import { Smith,
|
|
478
|
+
import { Smith, Touchstone } from 'smithkit';
|
|
447
479
|
|
|
448
480
|
async function showMeasurement(file: File): Promise<Smith> {
|
|
449
|
-
const { samples, referenceImpedanceOhms } =
|
|
481
|
+
const { samples, referenceImpedanceOhms } = Touchstone.parse(await file.text());
|
|
450
482
|
const chart = new Smith(referenceImpedanceOhms);
|
|
451
483
|
chart.draw('#smith');
|
|
452
484
|
chart.addTrace(samples, { name: file.name });
|
|
@@ -455,10 +487,43 @@ async function showMeasurement(file: File): Promise<Smith> {
|
|
|
455
487
|
```
|
|
456
488
|
|
|
457
489
|
Omitted options use Touchstone defaults: GHz, S, MA, 50 Ω. For an existing chart,
|
|
458
|
-
use `renormalizeSamples` when the file reference differs from
|
|
490
|
+
use `RfCalculations.renormalizeSamples` when the file reference differs from
|
|
459
491
|
`chart.referenceImpedanceOhms`. The parser itself does not renormalize data.
|
|
460
492
|
Multiport data and Touchstone 2.x are not supported.
|
|
461
493
|
|
|
494
|
+
## SVG export
|
|
495
|
+
|
|
496
|
+
`chart.toSvg()` and `scales.toSvg()` return SVG strings. Call them after `draw()`
|
|
497
|
+
while the component is mounted and has a non-zero rendered size; exporting before
|
|
498
|
+
mounting, from a `display: none` container, or after destruction throws an error.
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
const svg = chart.toSvg();
|
|
502
|
+
const blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });
|
|
503
|
+
const url = URL.createObjectURL(blob);
|
|
504
|
+
const link = document.createElement('a');
|
|
505
|
+
link.href = url;
|
|
506
|
+
link.download = 'smith-chart.svg';
|
|
507
|
+
document.body.appendChild(link);
|
|
508
|
+
link.click();
|
|
509
|
+
link.remove();
|
|
510
|
+
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
The chart export preserves the current zoom/pan, layer visibility, labels, traces,
|
|
514
|
+
markers, and visible indicators. It captures the rendered points, including dense
|
|
515
|
+
trace point reduction; it is an image export, not a measurement-data export.
|
|
516
|
+
The scale export combines all twelve axes into one SVG using their current layout
|
|
517
|
+
and displayed readings. To export a marker reading, call `scales.update()` with
|
|
518
|
+
that marker's reflection coefficient before `scales.toSvg()`.
|
|
519
|
+
|
|
520
|
+
Files have explicit pixel dimensions and a transparent background. Presentation
|
|
521
|
+
styles are inlined so the application's stylesheet is not required. Text remains
|
|
522
|
+
editable, and curved captions retain their internal path references. Font files
|
|
523
|
+
and surrounding HTML controls/backgrounds are not embedded. Downloading is the
|
|
524
|
+
consumer's responsibility; the library does not create files or modify live nodes.
|
|
525
|
+
The demo provides separate **Export chart SVG** and **Export scales SVG** buttons.
|
|
526
|
+
|
|
462
527
|
## Development and license
|
|
463
528
|
|
|
464
529
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development, testing, release, and demo
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MarkerSnapshot, MarkerComparison } from './measurements.js';
|
|
2
|
+
export declare class MarkerMeasurements {
|
|
3
|
+
private constructor();
|
|
4
|
+
/** Compare B against A without a chart or browser. Frequencies must be finite and non-negative. */
|
|
5
|
+
static compare(a: Pick<MarkerSnapshot, 'frequencyHz' | 'impedanceOhms' | 'reflectionCoefficient'>, b: Pick<MarkerSnapshot, 'frequencyHz' | 'impedanceOhms' | 'reflectionCoefficient'>): MarkerComparison;
|
|
6
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export class MarkerMeasurements {
|
|
2
|
+
constructor() { }
|
|
3
|
+
/** Compare B against A without a chart or browser. Frequencies must be finite and non-negative. */
|
|
4
|
+
static compare(a, b) {
|
|
5
|
+
if (![a.frequencyHz, b.frequencyHz].every((frequencyHz) => Number.isFinite(frequencyHz) && frequencyHz >= 0)) {
|
|
6
|
+
throw new RangeError('Marker frequencies must be finite and non-negative.');
|
|
7
|
+
}
|
|
8
|
+
const isFinite = (value) => Number.isFinite(value.re) && Number.isFinite(value.im);
|
|
9
|
+
const hasPhase = (gamma) => isFinite(gamma) && (gamma.re !== 0 || gamma.im !== 0);
|
|
10
|
+
const phaseDelta = hasPhase(a.reflectionCoefficient) && hasPhase(b.reflectionCoefficient)
|
|
11
|
+
? ((b.reflectionCoefficient.arg() - a.reflectionCoefficient.arg()) * 180) / Math.PI
|
|
12
|
+
: undefined;
|
|
13
|
+
const impedanceDelta = a.impedanceOhms && b.impedanceOhms && isFinite(a.impedanceOhms) && isFinite(b.impedanceOhms)
|
|
14
|
+
? b.impedanceOhms.sub(a.impedanceOhms)
|
|
15
|
+
: undefined;
|
|
16
|
+
return {
|
|
17
|
+
frequencyDeltaHz: b.frequencyHz - a.frequencyHz,
|
|
18
|
+
impedanceDeltaOhms: impedanceDelta && isFinite(impedanceDelta) ? impedanceDelta : undefined,
|
|
19
|
+
phaseDeltaDegrees: phaseDelta === undefined ? undefined : ((phaseDelta + 540) % 360) - 180,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
package/dist/lib/Smith.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { TraceSamples } from './samples.js';
|
|
2
2
|
import type { ChartLayers, PeripheralScales } from './layers.js';
|
|
3
|
-
import type { SmithReading } from './rf.js';
|
|
3
|
+
import type { SmithReading } from './rf/RfCalculations.js';
|
|
4
4
|
import type { TraceOptions, TraceUpdateOptions, TraceInfo, MarkerSnapshot, MarkerComparison } from './measurements.js';
|
|
5
5
|
export declare enum SmithEventType {
|
|
6
6
|
Cursor = "cursor",
|
|
7
7
|
Marker = "marker",
|
|
8
|
+
MarkerSelect = "marker-select",
|
|
8
9
|
MarkerDragStart = "marker-drag-start",
|
|
9
10
|
MarkerDragEnd = "marker-drag-end"
|
|
10
11
|
}
|
|
@@ -12,19 +13,21 @@ export type SmithEvent = {
|
|
|
12
13
|
type: SmithEventType.Cursor;
|
|
13
14
|
data: SmithReading | undefined;
|
|
14
15
|
} | {
|
|
15
|
-
type: SmithEventType.Marker | SmithEventType.MarkerDragStart | SmithEventType.MarkerDragEnd;
|
|
16
|
+
type: SmithEventType.Marker | SmithEventType.MarkerSelect | SmithEventType.MarkerDragStart | SmithEventType.MarkerDragEnd;
|
|
16
17
|
data: MarkerSnapshot;
|
|
17
18
|
};
|
|
18
19
|
export declare class Smith {
|
|
19
20
|
private referenceOhms;
|
|
20
21
|
private calcs;
|
|
21
22
|
private scalers;
|
|
23
|
+
private readonly defaultTransform;
|
|
22
24
|
private transform;
|
|
23
25
|
private zoomEnabled;
|
|
24
26
|
private applyingView;
|
|
25
27
|
private zoomBehavior;
|
|
26
28
|
private svg;
|
|
27
29
|
private resizeObserver;
|
|
30
|
+
private readonly labelLayout;
|
|
28
31
|
private container;
|
|
29
32
|
private dataContainer;
|
|
30
33
|
private markerContainer;
|
|
@@ -52,6 +55,8 @@ export declare class Smith {
|
|
|
52
55
|
readonly peripheralScales: PeripheralScales;
|
|
53
56
|
constructor(referenceOhms?: number);
|
|
54
57
|
draw(target: string | HTMLElement): void;
|
|
58
|
+
/** Export the current mounted view as standalone SVG with a transparent background. */
|
|
59
|
+
toSvg(): string;
|
|
55
60
|
/** Remove this chart and release its event handlers. Safe to call more than once. */
|
|
56
61
|
destroy(): void;
|
|
57
62
|
private updateViewportScale;
|
|
@@ -85,6 +90,8 @@ export declare class Smith {
|
|
|
85
90
|
/** Place a marker on an existing sample; no interpolation is performed. */
|
|
86
91
|
addMarker(traceId: string, sampleIndex?: number): string | undefined;
|
|
87
92
|
removeMarker(id: string): boolean;
|
|
93
|
+
/** Focus a mounted, visible marker for keyboard interaction. */
|
|
94
|
+
focusMarker(id: string): boolean;
|
|
88
95
|
setMarkerSample(id: string, sampleIndex: number): boolean;
|
|
89
96
|
/** Select the nearest measured frequency; ties choose the earliest input sample. */
|
|
90
97
|
setMarkerFrequency(id: string, frequencyHz: number): boolean;
|