smithkit 0.1.1 → 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 +119 -40
- 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 +68 -36
- 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 +4 -6
- package/dist/lib/{draw → grid}/ConstCircles.js +2 -2
- 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 +4 -2
- package/dist/lib/scales/SmithPeripheralScales.js +46 -26
- package/dist/lib/scales/SmithScales.d.ts +3 -1
- package/dist/lib/scales/SmithScales.js +8 -2
- 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,17 +5,22 @@ 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
|
|
@@ -63,11 +68,11 @@ must be finite and non-negative; both coordinates must be finite. A trace must
|
|
|
63
68
|
contain at least one sample.
|
|
64
69
|
|
|
65
70
|
Each new trace receives one marker on its first sample. Drag markers to select
|
|
66
|
-
samples, scroll to zoom, and drag the chart to pan. Markers
|
|
67
|
-
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.
|
|
68
73
|
|
|
69
74
|
Construct `Smith` only in a browser, such as your framework's mount hook. Importing
|
|
70
|
-
the package and using its calculation or parsing
|
|
75
|
+
the package and using its calculation or parsing methods does not require a DOM.
|
|
71
76
|
|
|
72
77
|
Zoom is enabled by default. For a fixed view, call `chart.setZoomEnabled(false)` before or after mounting.
|
|
73
78
|
It disables wheel/double-click zoom and mouse/touch panning and pinch zoom while
|
|
@@ -89,6 +94,25 @@ chart.draw('#smith');
|
|
|
89
94
|
container throws. Call `chart.destroy()` on unmount; it removes the SVG, releases
|
|
90
95
|
event handlers, and cancels queued notifications. Repeated destruction is safe.
|
|
91
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
|
+
|
|
92
116
|
## Traces and markers
|
|
93
117
|
|
|
94
118
|
Trace and marker IDs are opaque strings, unique within a chart and never reused
|
|
@@ -121,6 +145,7 @@ chart.removeMarker(markerB);
|
|
|
121
145
|
| `clearTraces()` | Removes all traces and their markers. |
|
|
122
146
|
| `addMarker(traceId, sampleIndex = 0)` | Returns a marker ID, or `undefined` if the trace is missing. |
|
|
123
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. |
|
|
124
149
|
| `setMarkerSample(id, sampleIndex)` | Selects an existing sample and queues a marker notification. |
|
|
125
150
|
| `removeMarker(id)` | Removes one marker without renumbering the remaining markers. |
|
|
126
151
|
| `compareMarkers(a, b)` | Returns B − A, or `undefined` if either marker is missing. |
|
|
@@ -192,7 +217,7 @@ const unsubscribe = chart.onEvent((event) => {
|
|
|
192
217
|
console.log(event.data?.impedanceOhms?.toVector());
|
|
193
218
|
return;
|
|
194
219
|
}
|
|
195
|
-
// Marker, MarkerDragStart, and MarkerDragEnd
|
|
220
|
+
// Marker, MarkerSelect, MarkerDragStart, and MarkerDragEnd carry a MarkerSnapshot.
|
|
196
221
|
console.log(event.data.markerId, event.data.frequencyHz);
|
|
197
222
|
});
|
|
198
223
|
|
|
@@ -202,7 +227,12 @@ chart.destroy();
|
|
|
202
227
|
```
|
|
203
228
|
|
|
204
229
|
The event types are `Cursor` (`'cursor'`), `Marker` (`'marker'`),
|
|
230
|
+
`MarkerSelect` (`'marker-select'`),
|
|
205
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.
|
|
206
236
|
Cursor movement is suspended during marker dragging. Drag start/end events fire
|
|
207
237
|
synchronously; marker position notifications are queued and report the latest
|
|
208
238
|
snapshot at delivery. Before delivery, repeated updates to the same marker coalesce
|
|
@@ -213,7 +243,7 @@ Trace metadata changes do not emit marker events; refresh metadata after mutatio
|
|
|
213
243
|
Destruction suppresses application callbacks.
|
|
214
244
|
|
|
215
245
|
`chart.cursorReading` returns the last cursor position. Cursor and marker readings
|
|
216
|
-
share `SmithReading`; `readReflection(gamma, referenceImpedanceOhms = 50)` produces
|
|
246
|
+
share `SmithReading`; `RfCalculations.readReflection(gamma, referenceImpedanceOhms = 50)` produces
|
|
217
247
|
the same reading without constructing a chart.
|
|
218
248
|
|
|
219
249
|
| Fields | Units / meaning |
|
|
@@ -239,7 +269,7 @@ infinite scalar limit is preserved: perfect match gives infinite return loss;
|
|
|
239
269
|
For active loads (\|Γ\| > 1), VSWR, standing-wave quantities, reflection loss,
|
|
240
270
|
attenuation, and power transmission are `undefined`. Other quantities remain
|
|
241
271
|
available. Non-finite complex inputs or invalid reference impedances throw
|
|
242
|
-
`RangeError` in the public RF
|
|
272
|
+
`RangeError` in the public RF methods. Unrepresentable complex conversion
|
|
243
273
|
results are `undefined`.
|
|
244
274
|
|
|
245
275
|
## Selecting a marker by frequency
|
|
@@ -259,22 +289,22 @@ measurement frequency; dragging and sample selection keep that field synchronize
|
|
|
259
289
|
## Calculations without a chart
|
|
260
290
|
|
|
261
291
|
```ts
|
|
262
|
-
import { Complex,
|
|
292
|
+
import { Complex, RfCalculations } from 'smithkit';
|
|
263
293
|
|
|
264
|
-
const gamma = impedanceToReflection(Complex.from(75, 25), 50)!;
|
|
265
|
-
const reading = readReflection(gamma, 50);
|
|
294
|
+
const gamma = RfCalculations.impedanceToReflection(Complex.from(75, 25), 50)!;
|
|
295
|
+
const reading = RfCalculations.readReflection(gamma, 50);
|
|
266
296
|
console.log(reading.impedanceOhms?.toVector()); // Approximately [75, 25].
|
|
267
297
|
console.log(reading.admittanceSiemens?.toVector());
|
|
268
298
|
```
|
|
269
299
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
| `reflectionToImpedance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Z in Ω. |
|
|
273
|
-
| `impedanceToReflection(impedanceOhms, referenceImpedanceOhms = 50)` | Physical Z in Ω → Γ. |
|
|
274
|
-
| `reflectionToAdmittance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Y in S. |
|
|
275
|
-
| `admittanceToReflection(admittanceSiemens, referenceImpedanceOhms = 50)` | Physical Y in S → Γ. |
|
|
276
|
-
| `readReflection(gamma, referenceImpedanceOhms = 50)` | Complete `SmithReading`. |
|
|
277
|
-
| `
|
|
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`. |
|
|
278
308
|
|
|
279
309
|
Comparison results contain `frequencyDeltaHz`, `impedanceDeltaOhms`, and
|
|
280
310
|
`phaseDeltaDegrees`. Phase differences use B − A wrapped to **[−180°, 180°)**:
|
|
@@ -285,27 +315,27 @@ a point comparison, not sweep phase unwrapping or group delay.
|
|
|
285
315
|
|
|
286
316
|
`Complex.from(re, im)` constructs complex numbers. Read components through `re` and `im`. Arithmetic (`add`, `sub`,
|
|
287
317
|
`mul`, `div`, `pow`) returns new values. The class also provides `abs`, `arg`
|
|
288
|
-
(radians), and static
|
|
318
|
+
(radians), and static methods such as `Complex.conj`, `Complex.sqrt`,
|
|
289
319
|
`Complex.exp`, `Complex.log`, and trigonometric/hyperbolic functions and inverses. `toVector()` returns `[real, imaginary]`; `toString(dp)` formats
|
|
290
320
|
a Cartesian value. See the exported declarations for all operations.
|
|
291
321
|
|
|
292
|
-
|
|
293
|
-
digits and SI prefixes), `
|
|
294
|
-
`
|
|
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
|
|
295
325
|
without a chart or DOM. Complex formatters default to three fractional digits.
|
|
296
|
-
`
|
|
326
|
+
`SmithFormatter.number` includes spacing so you can append a unit, e.g. `SmithFormatter.number(1e9) + 'Hz'`.
|
|
297
327
|
|
|
298
|
-
`reactanceToComponent(reactanceOhms, frequencyHz)` calculates an ideal equivalent
|
|
328
|
+
`RfCalculations.reactanceToComponent(reactanceOhms, frequencyHz)` calculates an ideal equivalent
|
|
299
329
|
series component without formatting or constructing a chart:
|
|
300
330
|
|
|
301
331
|
```ts
|
|
302
|
-
import {
|
|
332
|
+
import { RfCalculations, SmithFormatter } from 'smithkit';
|
|
303
333
|
|
|
304
|
-
const component = reactanceToComponent(-50, 1e9);
|
|
334
|
+
const component = RfCalculations.reactanceToComponent(-50, 1e9);
|
|
305
335
|
if (component?.kind === 'capacitor') {
|
|
306
|
-
console.log(
|
|
336
|
+
console.log(SmithFormatter.number(component.capacitanceFarads) + 'F'); // 3.18 pF
|
|
307
337
|
} else if (component?.kind === 'inductor') {
|
|
308
|
-
console.log(
|
|
338
|
+
console.log(SmithFormatter.number(component.inductanceHenries) + 'H');
|
|
309
339
|
}
|
|
310
340
|
```
|
|
311
341
|
|
|
@@ -333,9 +363,10 @@ chart.layers.vswr.setVisible(true);
|
|
|
333
363
|
The four grid layers support `setVisible`, `setMinorVisible`, and
|
|
334
364
|
`setStyle(Partial<GridStyle>)`. Style fields: `stroke`, `majorWidth`, `minorWidth`,
|
|
335
365
|
`textColor`, `textFontFamily`, `textFontSize`. Widths are positive finite numbers
|
|
336
|
-
in CSS pixels. Font size is a positive finite
|
|
337
|
-
|
|
338
|
-
|
|
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.
|
|
339
370
|
|
|
340
371
|
`layers.q` and `layers.vswr` support `setVisible`,
|
|
341
372
|
`setStyle({ stroke?, strokeWidth? })`, `addValue`, and `removeValue`.
|
|
@@ -345,8 +376,23 @@ Duplicate additions and removal of absent values have no effect.
|
|
|
345
376
|
|
|
346
377
|
Grid labels use normalized values; readings use physical units. Strokes default
|
|
347
378
|
to slate gray with 1 px major and 0.6 px minor lines. Stroke widths stay constant
|
|
348
|
-
under zoom
|
|
349
|
-
|
|
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.
|
|
350
396
|
|
|
351
397
|
## Parameter scales
|
|
352
398
|
|
|
@@ -404,12 +450,12 @@ result rejects the operation without changing Z₀ or data. Active marker drags
|
|
|
404
450
|
cursor indicators are cleared, and marker readings are queued with the new values.
|
|
405
451
|
Changing to the current Z₀ has no effect. Mutations after destruction throw.
|
|
406
452
|
|
|
407
|
-
Two DOM-independent
|
|
453
|
+
Two DOM-independent methods are available on `RfCalculations`:
|
|
408
454
|
|
|
409
|
-
- `renormalizeReflection(gamma, fromOhms, toOhms)` returns the new complex Γ or
|
|
455
|
+
- `RfCalculations.renormalizeReflection(gamma, fromOhms, toOhms)` returns the new complex Γ or
|
|
410
456
|
`undefined` for a singular/unrepresentable result. Exact open and short limits
|
|
411
457
|
remain Γ = +1 and −1. References must be positive, finite, real ohm values.
|
|
412
|
-
- `renormalizeSamples(samples, fromOhms, toOhms)` returns a new sample array in
|
|
458
|
+
- `RfCalculations.renormalizeSamples(samples, fromOhms, toOhms)` returns a new sample array in
|
|
413
459
|
the same order, preserving frequencies. Invalid samples or a singular result
|
|
414
460
|
throw `RangeError`; the input is never modified.
|
|
415
461
|
|
|
@@ -424,15 +470,15 @@ multiport renormalization are outside the supported scope.
|
|
|
424
470
|
|
|
425
471
|
## Touchstone import
|
|
426
472
|
|
|
427
|
-
`
|
|
473
|
+
`Touchstone.parse(text)` returns `{ samples, referenceImpedanceOhms }`. It accepts
|
|
428
474
|
one-port Touchstone 1.x, converts RI/MA/DB into Cartesian Γ and all frequencies
|
|
429
475
|
into Hz, and throws for unsupported or invalid input.
|
|
430
476
|
|
|
431
477
|
```ts
|
|
432
|
-
import { Smith,
|
|
478
|
+
import { Smith, Touchstone } from 'smithkit';
|
|
433
479
|
|
|
434
480
|
async function showMeasurement(file: File): Promise<Smith> {
|
|
435
|
-
const { samples, referenceImpedanceOhms } =
|
|
481
|
+
const { samples, referenceImpedanceOhms } = Touchstone.parse(await file.text());
|
|
436
482
|
const chart = new Smith(referenceImpedanceOhms);
|
|
437
483
|
chart.draw('#smith');
|
|
438
484
|
chart.addTrace(samples, { name: file.name });
|
|
@@ -441,10 +487,43 @@ async function showMeasurement(file: File): Promise<Smith> {
|
|
|
441
487
|
```
|
|
442
488
|
|
|
443
489
|
Omitted options use Touchstone defaults: GHz, S, MA, 50 Ω. For an existing chart,
|
|
444
|
-
use `renormalizeSamples` when the file reference differs from
|
|
490
|
+
use `RfCalculations.renormalizeSamples` when the file reference differs from
|
|
445
491
|
`chart.referenceImpedanceOhms`. The parser itself does not renormalize data.
|
|
446
492
|
Multiport data and Touchstone 2.x are not supported.
|
|
447
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
|
+
|
|
448
527
|
## Development and license
|
|
449
528
|
|
|
450
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;
|
package/dist/lib/Smith.js
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
import * as d3 from 'd3';
|
|
2
|
-
import { MouseGesture } from './
|
|
3
|
-
import { SmithSvg } from './
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
2
|
+
import { MouseGesture } from './interaction/MouseGesture.js';
|
|
3
|
+
import { SmithSvg } from './svg/SmithSvg.js';
|
|
4
|
+
import { LabelLayout } from './svg/LabelLayout.js';
|
|
5
|
+
import { SvgExporter } from './svg/SvgExporter.js';
|
|
6
|
+
import { SmithGroup } from './svg/SmithGroup.js';
|
|
7
|
+
import { SmithCircle } from './svg/SmithCircle.js';
|
|
8
|
+
import { SmithData } from './traces/SmithData.js';
|
|
9
|
+
import { SmithCursor } from './interaction/SmithCursor.js';
|
|
10
|
+
import { ConstResistance } from './grid/ConstResistance.js';
|
|
11
|
+
import { ConstReactance } from './grid/ConstReactance.js';
|
|
12
|
+
import { ConstConductance } from './grid/ConstConductance.js';
|
|
13
|
+
import { ConstSusceptance } from './grid/ConstSusceptance.js';
|
|
14
|
+
import { ConstQCircles } from './grid/ConstQCircles.js';
|
|
15
|
+
import { ConstSwrCircles } from './grid/ConstSwrCircles.js';
|
|
16
|
+
import { SmithScaler } from './svg/SmithScaler.js';
|
|
17
|
+
import { SmithConstantCircle } from './rf/SmithConstantCircle.js';
|
|
18
|
+
import { GridDefinitions } from './grid/GridDefinitions.js';
|
|
19
|
+
import { Complex } from './math/Complex.js';
|
|
18
20
|
import { SmithPeripheralScales } from './scales/SmithPeripheralScales.js';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
21
|
+
import { GridLayerControl } from './grid/GridLayerControl.js';
|
|
22
|
+
import { CircleLayerControl } from './grid/CircleLayerControl.js';
|
|
23
|
+
import { RfCalculations } from './rf/RfCalculations.js';
|
|
24
|
+
import { MarkerMeasurements } from './MarkerMeasurements.js';
|
|
23
25
|
export var SmithEventType;
|
|
24
26
|
(function (SmithEventType) {
|
|
25
27
|
SmithEventType["Cursor"] = "cursor";
|
|
26
28
|
SmithEventType["Marker"] = "marker";
|
|
29
|
+
SmithEventType["MarkerSelect"] = "marker-select";
|
|
27
30
|
SmithEventType["MarkerDragStart"] = "marker-drag-start";
|
|
28
31
|
SmithEventType["MarkerDragEnd"] = "marker-drag-end";
|
|
29
32
|
})(SmithEventType || (SmithEventType = {}));
|
|
@@ -31,12 +34,14 @@ export class Smith {
|
|
|
31
34
|
referenceOhms;
|
|
32
35
|
calcs = new SmithConstantCircle();
|
|
33
36
|
scalers;
|
|
37
|
+
defaultTransform = d3.zoomIdentity.translate(62.5, 62.5).scale(0.75);
|
|
34
38
|
transform = d3.zoomIdentity;
|
|
35
39
|
zoomEnabled = true;
|
|
36
40
|
applyingView = false;
|
|
37
41
|
zoomBehavior = d3.zoom();
|
|
38
42
|
svg;
|
|
39
43
|
resizeObserver;
|
|
44
|
+
labelLayout;
|
|
40
45
|
container;
|
|
41
46
|
dataContainer;
|
|
42
47
|
markerContainer;
|
|
@@ -68,7 +73,7 @@ export class Smith {
|
|
|
68
73
|
throw new RangeError('Reference impedance must be positive and finite.');
|
|
69
74
|
}
|
|
70
75
|
const viewBoxSize = 500;
|
|
71
|
-
const gridData =
|
|
76
|
+
const gridData = GridDefinitions.create();
|
|
72
77
|
this.scalers = this.createScalers(viewBoxSize);
|
|
73
78
|
this.svg = new SmithSvg(viewBoxSize);
|
|
74
79
|
this.container = new SmithGroup();
|
|
@@ -122,7 +127,6 @@ export class Smith {
|
|
|
122
127
|
this.container.append(this.reactanceAxis);
|
|
123
128
|
this.container.append(cursorContainer);
|
|
124
129
|
this.container.append(this.dataContainer);
|
|
125
|
-
this.container.append(this.markerContainer);
|
|
126
130
|
const labels = new SmithGroup().attr('data-layer', 'labels').attr('pointer-events', 'none');
|
|
127
131
|
for (const [name, layer] of [
|
|
128
132
|
['conductance', this.constConductance],
|
|
@@ -134,14 +138,16 @@ export class Smith {
|
|
|
134
138
|
}
|
|
135
139
|
labels.append(this.peripheralScaleRenderer.labels);
|
|
136
140
|
this.container.append(labels);
|
|
141
|
+
this.container.append(this.markerContainer);
|
|
142
|
+
this.labelLayout = new LabelLayout(this.svg.Node, labels.Node, this.defaultTransform);
|
|
137
143
|
const assertAlive = () => this.assertAlive();
|
|
138
144
|
this.layers = {
|
|
139
|
-
resistance:
|
|
140
|
-
reactance:
|
|
141
|
-
conductance:
|
|
142
|
-
susceptance:
|
|
143
|
-
q:
|
|
144
|
-
vswr:
|
|
145
|
+
resistance: new GridLayerControl(this.constResistance, assertAlive, () => this.labelLayout.update(true)),
|
|
146
|
+
reactance: new GridLayerControl(this.constReactance, assertAlive, () => this.labelLayout.update(true)),
|
|
147
|
+
conductance: new GridLayerControl(this.constConductance, assertAlive, () => this.labelLayout.update(true)),
|
|
148
|
+
susceptance: new GridLayerControl(this.constSusceptance, assertAlive, () => this.labelLayout.update(true)),
|
|
149
|
+
q: new CircleLayerControl(this.constQCircles, 0, assertAlive),
|
|
150
|
+
vswr: new CircleLayerControl(this.constSwrCircles, 1, assertAlive),
|
|
145
151
|
};
|
|
146
152
|
this.peripheralScales = {
|
|
147
153
|
setVisible: (visible) => {
|
|
@@ -152,6 +158,7 @@ export class Smith {
|
|
|
152
158
|
else {
|
|
153
159
|
this.peripheralScaleRenderer.hide();
|
|
154
160
|
}
|
|
161
|
+
this.labelLayout.update(true);
|
|
155
162
|
},
|
|
156
163
|
update: (gamma) => {
|
|
157
164
|
assertAlive();
|
|
@@ -171,6 +178,11 @@ export class Smith {
|
|
|
171
178
|
host.appendChild(this.svg.Node);
|
|
172
179
|
this.updateViewportScale();
|
|
173
180
|
}
|
|
181
|
+
/** Export the current mounted view as standalone SVG with a transparent background. */
|
|
182
|
+
toSvg() {
|
|
183
|
+
this.assertAlive();
|
|
184
|
+
return SvgExporter.chart(this.svg.Node);
|
|
185
|
+
}
|
|
174
186
|
/** Remove this chart and release its event handlers. Safe to call more than once. */
|
|
175
187
|
destroy() {
|
|
176
188
|
if (this.destroyed) {
|
|
@@ -196,6 +208,7 @@ export class Smith {
|
|
|
196
208
|
const scale = Math.hypot(matrix.a, matrix.b);
|
|
197
209
|
this.data.forEach((trace) => trace.setViewportScale(scale));
|
|
198
210
|
}
|
|
211
|
+
this.labelLayout.update();
|
|
199
212
|
}
|
|
200
213
|
assertAlive() {
|
|
201
214
|
if (this.destroyed) {
|
|
@@ -252,19 +265,22 @@ export class Smith {
|
|
|
252
265
|
}
|
|
253
266
|
/** Last cursor position. Use cursor events to detect pointer leave. */
|
|
254
267
|
get cursorReading() {
|
|
255
|
-
return readReflection(this.cursor.Position, this.referenceImpedanceOhms);
|
|
268
|
+
return RfCalculations.readReflection(this.cursor.Position, this.referenceImpedanceOhms);
|
|
256
269
|
}
|
|
257
270
|
initializeZoom() {
|
|
258
271
|
const zoom = this.zoomBehavior
|
|
259
272
|
.scaleExtent([0.6, 1000])
|
|
260
|
-
.filter((event) => this.zoomEnabled &&
|
|
273
|
+
.filter((event) => this.zoomEnabled &&
|
|
274
|
+
this.draggedMarkers.size === 0 &&
|
|
275
|
+
(!event.ctrlKey || event.type === 'wheel') &&
|
|
276
|
+
!event.button)
|
|
261
277
|
.on('start', (event) => {
|
|
262
278
|
if (event.sourceEvent) {
|
|
263
279
|
this.mouseGesture.capture(event.sourceEvent, 'zoom');
|
|
264
280
|
}
|
|
265
281
|
})
|
|
266
282
|
.on('zoom', (event) => {
|
|
267
|
-
if (!this.zoomEnabled && !this.applyingView) {
|
|
283
|
+
if ((!this.zoomEnabled || this.draggedMarkers.size > 0) && !this.applyingView) {
|
|
268
284
|
// An already active mouse/touch gesture still needs its normal end event.
|
|
269
285
|
// Restore D3's view through its public API while that gesture finishes.
|
|
270
286
|
this.applyView(this.transform);
|
|
@@ -300,7 +316,7 @@ export class Smith {
|
|
|
300
316
|
}
|
|
301
317
|
resetView() {
|
|
302
318
|
this.assertAlive();
|
|
303
|
-
const transform =
|
|
319
|
+
const transform = this.defaultTransform;
|
|
304
320
|
this.applyView(transform);
|
|
305
321
|
}
|
|
306
322
|
onZoom(transform) {
|
|
@@ -411,6 +427,7 @@ export class Smith {
|
|
|
411
427
|
data.setStyle(options);
|
|
412
428
|
if (options.name !== undefined) {
|
|
413
429
|
this.traceMetadata.get(data).name = options.name.trim();
|
|
430
|
+
data.setName(options.name.trim());
|
|
414
431
|
}
|
|
415
432
|
if (options.color !== undefined) {
|
|
416
433
|
data.setColor(options.color);
|
|
@@ -459,6 +476,14 @@ export class Smith {
|
|
|
459
476
|
const location = this.findMarker(id);
|
|
460
477
|
return location ? this.data[location.datasetNo].removeMarker(location.markerNo) : false;
|
|
461
478
|
}
|
|
479
|
+
/** Focus a mounted, visible marker for keyboard interaction. */
|
|
480
|
+
focusMarker(id) {
|
|
481
|
+
this.assertAlive();
|
|
482
|
+
const location = this.findMarker(id);
|
|
483
|
+
return location
|
|
484
|
+
? this.data[location.datasetNo].Markers[location.markerNo].marker.focus()
|
|
485
|
+
: false;
|
|
486
|
+
}
|
|
462
487
|
setMarkerSample(id, sampleIndex) {
|
|
463
488
|
this.assertAlive();
|
|
464
489
|
const location = this.findMarker(id);
|
|
@@ -482,7 +507,7 @@ export class Smith {
|
|
|
482
507
|
const data = this.data[location.datasetNo];
|
|
483
508
|
const marker = data.Markers[location.markerNo];
|
|
484
509
|
return {
|
|
485
|
-
...readReflection(Complex.from(...marker.selectedPoint.reflectionCoefficient), this.referenceImpedanceOhms),
|
|
510
|
+
...RfCalculations.readReflection(Complex.from(...marker.selectedPoint.reflectionCoefficient), this.referenceImpedanceOhms),
|
|
486
511
|
frequencyHz: marker.selectedPoint.frequencyHz,
|
|
487
512
|
traceId: this.traceMetadata.get(data).id,
|
|
488
513
|
markerId: id,
|
|
@@ -494,7 +519,7 @@ export class Smith {
|
|
|
494
519
|
compareMarkers(a, b) {
|
|
495
520
|
const first = this.getMarker(a);
|
|
496
521
|
const second = this.getMarker(b);
|
|
497
|
-
return first && second ?
|
|
522
|
+
return first && second ? MarkerMeasurements.compare(first, second) : undefined;
|
|
498
523
|
}
|
|
499
524
|
/** Current positive real reference impedance, in ohms. */
|
|
500
525
|
get referenceImpedanceOhms() {
|
|
@@ -504,11 +529,11 @@ export class Smith {
|
|
|
504
529
|
renormalize(referenceImpedanceOhms) {
|
|
505
530
|
this.assertAlive();
|
|
506
531
|
// Validate even with no traces, and prepare every result before changing any state.
|
|
507
|
-
renormalizeSamples([], this.referenceOhms, referenceImpedanceOhms);
|
|
532
|
+
RfCalculations.renormalizeSamples([], this.referenceOhms, referenceImpedanceOhms);
|
|
508
533
|
if (referenceImpedanceOhms === this.referenceOhms) {
|
|
509
534
|
return;
|
|
510
535
|
}
|
|
511
|
-
const samples = this.data.map((data) => renormalizeSamples(data.Samples, this.referenceOhms, referenceImpedanceOhms));
|
|
536
|
+
const samples = this.data.map((data) => RfCalculations.renormalizeSamples(data.Samples, this.referenceOhms, referenceImpedanceOhms));
|
|
512
537
|
this.data.forEach((data) => data.Markers.forEach((entry) => entry.marker.cancelDrag()));
|
|
513
538
|
this.referenceOhms = referenceImpedanceOhms;
|
|
514
539
|
this.data.forEach((data, index) => data.update(samples[index], 'sample-index'));
|
|
@@ -534,6 +559,13 @@ export class Smith {
|
|
|
534
559
|
}, this.markerContainer, options);
|
|
535
560
|
const number = this.nextTraceId++;
|
|
536
561
|
this.traceMetadata.set(data, { id: `trace-${number}`, name: `Trace ${number}` });
|
|
562
|
+
data.setName(`Trace ${number}`);
|
|
563
|
+
data.setMarkerSelectHandler((marker) => {
|
|
564
|
+
const snapshot = this.getMarker(this.markerId(marker));
|
|
565
|
+
if (snapshot) {
|
|
566
|
+
this.emit({ type: SmithEventType.MarkerSelect, data: snapshot });
|
|
567
|
+
}
|
|
568
|
+
});
|
|
537
569
|
data.setMarkerMoveHandler((index) => {
|
|
538
570
|
const marker = data.Markers[index];
|
|
539
571
|
const snapshot = marker && this.getMarker(this.markerId(marker.marker));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Complex } from './math/Complex.js';
|
|
2
|
+
export declare class SmithFormatter {
|
|
3
|
+
private constructor();
|
|
4
|
+
/** Format with three significant digits and an SI prefix; includes spacing before the unit. */
|
|
5
|
+
static number(value: number): string;
|
|
6
|
+
/** Format Cartesian components to decimalPlaces fractional digits. */
|
|
7
|
+
static complex(value: Complex, unit?: string, decimalPlaces?: number): string;
|
|
8
|
+
/** Format magnitude and phase in degrees to decimalPlaces fractional digits. */
|
|
9
|
+
static polar(value: Complex, unit?: string, decimalPlaces?: number): string;
|
|
10
|
+
}
|