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/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,15 +127,27 @@ export class Smith {
|
|
|
122
127
|
this.container.append(this.reactanceAxis);
|
|
123
128
|
this.container.append(cursorContainer);
|
|
124
129
|
this.container.append(this.dataContainer);
|
|
130
|
+
const labels = new SmithGroup().attr('data-layer', 'labels').attr('pointer-events', 'none');
|
|
131
|
+
for (const [name, layer] of [
|
|
132
|
+
['conductance', this.constConductance],
|
|
133
|
+
['susceptance', this.constSusceptance],
|
|
134
|
+
['resistance', this.constResistance],
|
|
135
|
+
['reactance', this.constReactance],
|
|
136
|
+
]) {
|
|
137
|
+
labels.append(layer.labels.attr('data-label-layer', name));
|
|
138
|
+
}
|
|
139
|
+
labels.append(this.peripheralScaleRenderer.labels);
|
|
140
|
+
this.container.append(labels);
|
|
125
141
|
this.container.append(this.markerContainer);
|
|
142
|
+
this.labelLayout = new LabelLayout(this.svg.Node, labels.Node, this.defaultTransform);
|
|
126
143
|
const assertAlive = () => this.assertAlive();
|
|
127
144
|
this.layers = {
|
|
128
|
-
resistance:
|
|
129
|
-
reactance:
|
|
130
|
-
conductance:
|
|
131
|
-
susceptance:
|
|
132
|
-
q:
|
|
133
|
-
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),
|
|
134
151
|
};
|
|
135
152
|
this.peripheralScales = {
|
|
136
153
|
setVisible: (visible) => {
|
|
@@ -141,6 +158,7 @@ export class Smith {
|
|
|
141
158
|
else {
|
|
142
159
|
this.peripheralScaleRenderer.hide();
|
|
143
160
|
}
|
|
161
|
+
this.labelLayout.update(true);
|
|
144
162
|
},
|
|
145
163
|
update: (gamma) => {
|
|
146
164
|
assertAlive();
|
|
@@ -160,6 +178,11 @@ export class Smith {
|
|
|
160
178
|
host.appendChild(this.svg.Node);
|
|
161
179
|
this.updateViewportScale();
|
|
162
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
|
+
}
|
|
163
186
|
/** Remove this chart and release its event handlers. Safe to call more than once. */
|
|
164
187
|
destroy() {
|
|
165
188
|
if (this.destroyed) {
|
|
@@ -185,6 +208,7 @@ export class Smith {
|
|
|
185
208
|
const scale = Math.hypot(matrix.a, matrix.b);
|
|
186
209
|
this.data.forEach((trace) => trace.setViewportScale(scale));
|
|
187
210
|
}
|
|
211
|
+
this.labelLayout.update();
|
|
188
212
|
}
|
|
189
213
|
assertAlive() {
|
|
190
214
|
if (this.destroyed) {
|
|
@@ -241,19 +265,22 @@ export class Smith {
|
|
|
241
265
|
}
|
|
242
266
|
/** Last cursor position. Use cursor events to detect pointer leave. */
|
|
243
267
|
get cursorReading() {
|
|
244
|
-
return readReflection(this.cursor.Position, this.referenceImpedanceOhms);
|
|
268
|
+
return RfCalculations.readReflection(this.cursor.Position, this.referenceImpedanceOhms);
|
|
245
269
|
}
|
|
246
270
|
initializeZoom() {
|
|
247
271
|
const zoom = this.zoomBehavior
|
|
248
272
|
.scaleExtent([0.6, 1000])
|
|
249
|
-
.filter((event) => this.zoomEnabled &&
|
|
273
|
+
.filter((event) => this.zoomEnabled &&
|
|
274
|
+
this.draggedMarkers.size === 0 &&
|
|
275
|
+
(!event.ctrlKey || event.type === 'wheel') &&
|
|
276
|
+
!event.button)
|
|
250
277
|
.on('start', (event) => {
|
|
251
278
|
if (event.sourceEvent) {
|
|
252
279
|
this.mouseGesture.capture(event.sourceEvent, 'zoom');
|
|
253
280
|
}
|
|
254
281
|
})
|
|
255
282
|
.on('zoom', (event) => {
|
|
256
|
-
if (!this.zoomEnabled && !this.applyingView) {
|
|
283
|
+
if ((!this.zoomEnabled || this.draggedMarkers.size > 0) && !this.applyingView) {
|
|
257
284
|
// An already active mouse/touch gesture still needs its normal end event.
|
|
258
285
|
// Restore D3's view through its public API while that gesture finishes.
|
|
259
286
|
this.applyView(this.transform);
|
|
@@ -289,7 +316,7 @@ export class Smith {
|
|
|
289
316
|
}
|
|
290
317
|
resetView() {
|
|
291
318
|
this.assertAlive();
|
|
292
|
-
const transform =
|
|
319
|
+
const transform = this.defaultTransform;
|
|
293
320
|
this.applyView(transform);
|
|
294
321
|
}
|
|
295
322
|
onZoom(transform) {
|
|
@@ -400,6 +427,7 @@ export class Smith {
|
|
|
400
427
|
data.setStyle(options);
|
|
401
428
|
if (options.name !== undefined) {
|
|
402
429
|
this.traceMetadata.get(data).name = options.name.trim();
|
|
430
|
+
data.setName(options.name.trim());
|
|
403
431
|
}
|
|
404
432
|
if (options.color !== undefined) {
|
|
405
433
|
data.setColor(options.color);
|
|
@@ -448,6 +476,14 @@ export class Smith {
|
|
|
448
476
|
const location = this.findMarker(id);
|
|
449
477
|
return location ? this.data[location.datasetNo].removeMarker(location.markerNo) : false;
|
|
450
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
|
+
}
|
|
451
487
|
setMarkerSample(id, sampleIndex) {
|
|
452
488
|
this.assertAlive();
|
|
453
489
|
const location = this.findMarker(id);
|
|
@@ -471,7 +507,7 @@ export class Smith {
|
|
|
471
507
|
const data = this.data[location.datasetNo];
|
|
472
508
|
const marker = data.Markers[location.markerNo];
|
|
473
509
|
return {
|
|
474
|
-
...readReflection(Complex.from(...marker.selectedPoint.reflectionCoefficient), this.referenceImpedanceOhms),
|
|
510
|
+
...RfCalculations.readReflection(Complex.from(...marker.selectedPoint.reflectionCoefficient), this.referenceImpedanceOhms),
|
|
475
511
|
frequencyHz: marker.selectedPoint.frequencyHz,
|
|
476
512
|
traceId: this.traceMetadata.get(data).id,
|
|
477
513
|
markerId: id,
|
|
@@ -483,7 +519,7 @@ export class Smith {
|
|
|
483
519
|
compareMarkers(a, b) {
|
|
484
520
|
const first = this.getMarker(a);
|
|
485
521
|
const second = this.getMarker(b);
|
|
486
|
-
return first && second ?
|
|
522
|
+
return first && second ? MarkerMeasurements.compare(first, second) : undefined;
|
|
487
523
|
}
|
|
488
524
|
/** Current positive real reference impedance, in ohms. */
|
|
489
525
|
get referenceImpedanceOhms() {
|
|
@@ -493,11 +529,11 @@ export class Smith {
|
|
|
493
529
|
renormalize(referenceImpedanceOhms) {
|
|
494
530
|
this.assertAlive();
|
|
495
531
|
// Validate even with no traces, and prepare every result before changing any state.
|
|
496
|
-
renormalizeSamples([], this.referenceOhms, referenceImpedanceOhms);
|
|
532
|
+
RfCalculations.renormalizeSamples([], this.referenceOhms, referenceImpedanceOhms);
|
|
497
533
|
if (referenceImpedanceOhms === this.referenceOhms) {
|
|
498
534
|
return;
|
|
499
535
|
}
|
|
500
|
-
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));
|
|
501
537
|
this.data.forEach((data) => data.Markers.forEach((entry) => entry.marker.cancelDrag()));
|
|
502
538
|
this.referenceOhms = referenceImpedanceOhms;
|
|
503
539
|
this.data.forEach((data, index) => data.update(samples[index], 'sample-index'));
|
|
@@ -523,6 +559,13 @@ export class Smith {
|
|
|
523
559
|
}, this.markerContainer, options);
|
|
524
560
|
const number = this.nextTraceId++;
|
|
525
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
|
+
});
|
|
526
569
|
data.setMarkerMoveHandler((index) => {
|
|
527
570
|
const marker = data.Markers[index];
|
|
528
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
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { format } from 'd3';
|
|
2
|
+
export class SmithFormatter {
|
|
3
|
+
constructor() { }
|
|
4
|
+
/** Format with three significant digits and an SI prefix; includes spacing before the unit. */
|
|
5
|
+
static number(value) {
|
|
6
|
+
const formatted = format('.3~s')(value);
|
|
7
|
+
return Number.isFinite(value) && /[a-zA-Zµ]$/.test(formatted)
|
|
8
|
+
? formatted.replace(/([a-zA-Zµ])$/, ' $1')
|
|
9
|
+
: formatted + ' ';
|
|
10
|
+
}
|
|
11
|
+
/** Format Cartesian components to decimalPlaces fractional digits. */
|
|
12
|
+
static complex(value, unit = '', decimalPlaces = 3) {
|
|
13
|
+
return `${value.toString(decimalPlaces)} ${unit === '' ? '' : `[${unit}]`}`;
|
|
14
|
+
}
|
|
15
|
+
/** Format magnitude and phase in degrees to decimalPlaces fractional digits. */
|
|
16
|
+
static polar(value, unit = '', decimalPlaces = 3) {
|
|
17
|
+
return `${value.abs().toFixed(decimalPlaces)} ${unit} ∠${((value.arg() * 180) / Math.PI).toFixed(decimalPlaces)}°`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConstQCircles } from './ConstQCircles.js';
|
|
2
|
+
import type { ConstSwrCircles } from './ConstSwrCircles.js';
|
|
3
|
+
import type { CircleLayer, CircleStyle } from '../layers.js';
|
|
4
|
+
import { LayerControl } from './LayerControl.js';
|
|
5
|
+
/** Exposes Q/VSWR circle controls without exposing the SVG renderer. */
|
|
6
|
+
export declare class CircleLayerControl extends LayerControl implements CircleLayer {
|
|
7
|
+
private readonly layer;
|
|
8
|
+
private readonly minimum;
|
|
9
|
+
constructor(layer: ConstQCircles | ConstSwrCircles, minimum: number, assertAlive: () => void);
|
|
10
|
+
setVisible(visible: boolean): void;
|
|
11
|
+
setStyle(style: Partial<CircleStyle>): void;
|
|
12
|
+
addValue(value: number): void;
|
|
13
|
+
removeValue(value: number): void;
|
|
14
|
+
private validateValue;
|
|
15
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { LayerControl } from './LayerControl.js';
|
|
2
|
+
/** Exposes Q/VSWR circle controls without exposing the SVG renderer. */
|
|
3
|
+
export class CircleLayerControl extends LayerControl {
|
|
4
|
+
layer;
|
|
5
|
+
minimum;
|
|
6
|
+
constructor(layer, minimum, assertAlive) {
|
|
7
|
+
super(assertAlive);
|
|
8
|
+
this.layer = layer;
|
|
9
|
+
this.minimum = minimum;
|
|
10
|
+
}
|
|
11
|
+
setVisible(visible) {
|
|
12
|
+
this.assertAlive();
|
|
13
|
+
this.layer.visibility(visible);
|
|
14
|
+
}
|
|
15
|
+
setStyle(style) {
|
|
16
|
+
this.assertAlive();
|
|
17
|
+
this.validateLengths(style, ['strokeWidth']);
|
|
18
|
+
if (style.stroke !== undefined) {
|
|
19
|
+
this.layer.Stroke = style.stroke;
|
|
20
|
+
}
|
|
21
|
+
if (style.strokeWidth !== undefined) {
|
|
22
|
+
this.layer.StrokeWidth = String(style.strokeWidth);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
addValue(value) {
|
|
26
|
+
this.assertAlive();
|
|
27
|
+
this.validateValue(value);
|
|
28
|
+
this.layer.append(value);
|
|
29
|
+
}
|
|
30
|
+
removeValue(value) {
|
|
31
|
+
this.assertAlive();
|
|
32
|
+
this.validateValue(value);
|
|
33
|
+
this.layer.remove(value);
|
|
34
|
+
}
|
|
35
|
+
validateValue(value) {
|
|
36
|
+
if (!Number.isFinite(value) || value < this.minimum || value <= 0) {
|
|
37
|
+
throw new RangeError(`Circle value must be finite, positive, and at least ${this.minimum}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type * as d3 from 'd3';
|
|
2
|
-
import { SmithGroup } from '
|
|
3
|
-
import { SmithScaler } from '
|
|
4
|
-
import { Line } from '../
|
|
5
|
-
import {
|
|
6
|
-
import { Point } from '../shapes/Point.js';
|
|
7
|
-
import { SmithConstantCircle } from '../SmithConstantCircle.js';
|
|
2
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
3
|
+
import { SmithScaler } from '../svg/SmithScaler.js';
|
|
4
|
+
import type { Line, Circle, Point } from '../math/geometry.js';
|
|
5
|
+
import { SmithConstantCircle } from '../rf/SmithConstantCircle.js';
|
|
8
6
|
export interface ArcData {
|
|
9
7
|
p1: Point;
|
|
10
8
|
p2: Point;
|
|
@@ -41,6 +39,8 @@ export declare abstract class ConstCircles {
|
|
|
41
39
|
showMinor(): void;
|
|
42
40
|
hideMinor(): void;
|
|
43
41
|
protected build(): SmithGroup;
|
|
42
|
+
/** Mount labels separately so every grid line is painted before any label. */
|
|
43
|
+
get labels(): SmithGroup;
|
|
44
44
|
draw(): SmithGroup;
|
|
45
45
|
setDrawOptions(opts: ConstCirclesDrawOptions): void;
|
|
46
46
|
set Stroke(stroke: string);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithConstantCircle } from '../SmithConstantCircle.js';
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithConstantCircle } from '../rf/SmithConstantCircle.js';
|
|
3
3
|
export class ConstCircles {
|
|
4
4
|
scaler;
|
|
5
5
|
calcs = new SmithConstantCircle();
|
|
@@ -12,17 +12,19 @@ export class ConstCircles {
|
|
|
12
12
|
}
|
|
13
13
|
visibility(visible) {
|
|
14
14
|
if (visible) {
|
|
15
|
-
this.
|
|
15
|
+
this.show();
|
|
16
16
|
}
|
|
17
17
|
else {
|
|
18
|
-
this.
|
|
18
|
+
this.hide();
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
show() {
|
|
22
22
|
this.container.show();
|
|
23
|
+
this.texts.show();
|
|
23
24
|
}
|
|
24
25
|
hide() {
|
|
25
26
|
this.container.hide();
|
|
27
|
+
this.texts.hide();
|
|
26
28
|
}
|
|
27
29
|
displayMinor(display) {
|
|
28
30
|
if (display) {
|
|
@@ -39,7 +41,12 @@ export class ConstCircles {
|
|
|
39
41
|
this.minor.hide();
|
|
40
42
|
}
|
|
41
43
|
build() {
|
|
42
|
-
|
|
44
|
+
this.texts.hide();
|
|
45
|
+
return this.container.append(this.minor).append(this.major).hide();
|
|
46
|
+
}
|
|
47
|
+
/** Mount labels separately so every grid line is painted before any label. */
|
|
48
|
+
get labels() {
|
|
49
|
+
return this.texts;
|
|
43
50
|
}
|
|
44
51
|
draw() {
|
|
45
52
|
return this.container;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithScaler } from '
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithScaler } from '../svg/SmithScaler.js';
|
|
3
3
|
interface ConstQDrawOptions {
|
|
4
4
|
stroke: string;
|
|
5
5
|
strokeWidth: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithArc } from '
|
|
3
|
-
import { SmithConstantCircle } from '../SmithConstantCircle.js';
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithArc } from '../svg/SmithArc.js';
|
|
3
|
+
import { SmithConstantCircle } from '../rf/SmithConstantCircle.js';
|
|
4
4
|
export class ConstQCircles {
|
|
5
5
|
scaler;
|
|
6
6
|
calcs = new SmithConstantCircle();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithScaler } from '
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithScaler } from '../svg/SmithScaler.js';
|
|
3
3
|
interface ConstSwrDrawOptions {
|
|
4
4
|
stroke: string;
|
|
5
5
|
strokeWidth: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SmithGroup } from '
|
|
2
|
-
import { SmithCircle } from '
|
|
3
|
-
import { SmithConstantCircle } from '../SmithConstantCircle.js';
|
|
1
|
+
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
+
import { SmithCircle } from '../svg/SmithCircle.js';
|
|
3
|
+
import { SmithConstantCircle } from '../rf/SmithConstantCircle.js';
|
|
4
4
|
export class ConstSwrCircles {
|
|
5
5
|
scaler;
|
|
6
6
|
calcs = new SmithConstantCircle();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SmithTicksData } from './types.js';
|
|
2
|
+
export declare class GridDefinitions {
|
|
3
|
+
private constructor();
|
|
4
|
+
private static readonly resistanceMajor;
|
|
5
|
+
private static readonly resistanceMinor;
|
|
6
|
+
private static readonly reactanceMajor;
|
|
7
|
+
private static readonly reactanceMinor;
|
|
8
|
+
private static resistanceArcs;
|
|
9
|
+
private static reactanceArcs;
|
|
10
|
+
/** Build fresh definitions so callers cannot mutate another chart's grid. */
|
|
11
|
+
static create(): SmithTicksData;
|
|
12
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export class GridDefinitions {
|
|
2
|
+
constructor() { }
|
|
3
|
+
static resistanceMajor = [
|
|
4
|
+
[[0.05, 0.15], 0.2, -0.2, false],
|
|
5
|
+
[[0.1, 0.3, 0.5, 0.7, 0.9], 2, -2, true],
|
|
6
|
+
[[0.2, 0.4, 0.6, 0.8, 1.2, 1.4, 1.6, 1.8], 5, -5, true],
|
|
7
|
+
[[1, 3, 5], 10, -10, true],
|
|
8
|
+
[[2, 4], 20, -20, true],
|
|
9
|
+
[[20], 50, -50, true],
|
|
10
|
+
];
|
|
11
|
+
static resistanceMinor = [
|
|
12
|
+
[[0.02, 0.04, 0.06, 0.08, 0.12, 0.14, 0.16, 0.18], 0.2, 0.5, false],
|
|
13
|
+
[[0.02, 0.04, 0.06, 0.08, 0.12, 0.14, 0.16, 0.18], -0.2, -0.5, false],
|
|
14
|
+
[[0.05, 0.15, 0.25, 0.35, 0.45], 0.5, 1, false],
|
|
15
|
+
[[0.05, 0.15, 0.25, 0.35, 0.45], -0.5, -1, false],
|
|
16
|
+
[
|
|
17
|
+
[
|
|
18
|
+
0.01, 0.02, 0.03, 0.04, 0.06, 0.07, 0.08, 0.09, 0.11, 0.12, 0.13, 0.14, 0.16, 0.17, 0.18,
|
|
19
|
+
0.19,
|
|
20
|
+
],
|
|
21
|
+
0.2,
|
|
22
|
+
-0.2,
|
|
23
|
+
false,
|
|
24
|
+
],
|
|
25
|
+
[[0.22, 0.24, 0.26, 0.28, 0.32, 0.34, 0.36, 0.38, 0.42, 0.44, 0.46, 0.48], 0.5, -0.5, false],
|
|
26
|
+
[[0.55, 0.65, 0.75, 0.85, 0.95], 2, -2, true],
|
|
27
|
+
[[1.1, 1.3, 1.5, 1.7, 1.9], 2, -2, false],
|
|
28
|
+
[[2.2, 2.4, 2.6, 2.8, 3.2, 3.4, 3.6, 3.8], 5, -5, true],
|
|
29
|
+
[[4.2, 4.4, 4.6, 4.8], 5, -5, false],
|
|
30
|
+
[[6, 8, 12, 14, 16, 18], 20, -20, true],
|
|
31
|
+
[[7, 9], 10, -10, true],
|
|
32
|
+
[[30, 40], 50, -50, true],
|
|
33
|
+
];
|
|
34
|
+
static reactanceMajor = [
|
|
35
|
+
[[0.05, 0.15], 0.2, 0],
|
|
36
|
+
[[0.1, 0.3, 0.5, 0.7, 0.9], 2, 0],
|
|
37
|
+
[[0.2, 0.4, 0.6, 0.8, 1.2, 1.4, 1.6, 1.8], 5, 0],
|
|
38
|
+
[[1, 3, 5], 10, 0],
|
|
39
|
+
[[2, 4, 10], 20, 0],
|
|
40
|
+
[[20], 50, 0],
|
|
41
|
+
];
|
|
42
|
+
static reactanceMinor = [
|
|
43
|
+
[
|
|
44
|
+
[
|
|
45
|
+
0.01, 0.02, 0.03, 0.04, 0.06, 0.07, 0.08, 0.09, 0.11, 0.12, 0.13, 0.14, 0.16, 0.17, 0.18,
|
|
46
|
+
0.19,
|
|
47
|
+
],
|
|
48
|
+
0.2,
|
|
49
|
+
0,
|
|
50
|
+
],
|
|
51
|
+
[[0.02, 0.04, 0.06, 0.08, 0.12, 0.14, 0.16, 0.18], 0.5, 0.2],
|
|
52
|
+
[[0.22, 0.24, 0.26, 0.28, 0.32, 0.34, 0.36, 0.38, 0.42, 0.44, 0.46, 0.48], 0.5, 0],
|
|
53
|
+
[[0.05, 0.15, 0.25, 0.35, 0.45], 1, 0.5],
|
|
54
|
+
[[0.55, 0.65, 0.75, 0.85, 0.95], 1, 0],
|
|
55
|
+
[[1.1, 1.3, 1.5, 1.7, 1.9], 2, 0],
|
|
56
|
+
[[2.2, 2.4, 2.6, 2.8, 3.2, 3.4, 3.6, 3.8, 4.2, 4.4, 4.6, 4.8], 5, 0],
|
|
57
|
+
[[6, 8, 14, 16, 18], 20, 0],
|
|
58
|
+
[[7, 9], 10, 0],
|
|
59
|
+
[[12, 30, 40], 50, 0],
|
|
60
|
+
];
|
|
61
|
+
static resistanceArcs(bands) {
|
|
62
|
+
return bands.flatMap(([values, from, to, largeArc]) => values.map((value) => [
|
|
63
|
+
value,
|
|
64
|
+
[
|
|
65
|
+
[from, from < 0 ? 1 : 0],
|
|
66
|
+
[to, to < 0 ? 1 : 0],
|
|
67
|
+
],
|
|
68
|
+
[largeArc, from > to],
|
|
69
|
+
]));
|
|
70
|
+
}
|
|
71
|
+
static reactanceArcs(bands) {
|
|
72
|
+
return bands.flatMap(([values, outer, inner]) => values.flatMap((value) => [
|
|
73
|
+
[
|
|
74
|
+
value,
|
|
75
|
+
[
|
|
76
|
+
[outer, 1],
|
|
77
|
+
[inner, 1],
|
|
78
|
+
],
|
|
79
|
+
[false, false],
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
-value,
|
|
83
|
+
[
|
|
84
|
+
[outer, 0],
|
|
85
|
+
[inner, 0],
|
|
86
|
+
],
|
|
87
|
+
[false, true],
|
|
88
|
+
],
|
|
89
|
+
]));
|
|
90
|
+
}
|
|
91
|
+
/** Build fresh definitions so callers cannot mutate another chart's grid. */
|
|
92
|
+
static create() {
|
|
93
|
+
return {
|
|
94
|
+
resistance: {
|
|
95
|
+
major: {
|
|
96
|
+
lines: [],
|
|
97
|
+
circles: [10, 50],
|
|
98
|
+
arcs: GridDefinitions.resistanceArcs(GridDefinitions.resistanceMajor),
|
|
99
|
+
},
|
|
100
|
+
minor: {
|
|
101
|
+
lines: [],
|
|
102
|
+
circles: [],
|
|
103
|
+
arcs: GridDefinitions.resistanceArcs(GridDefinitions.resistanceMinor),
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
reactance: {
|
|
107
|
+
major: {
|
|
108
|
+
lines: [{ p1: [-1, 0], p2: [1, 0] }],
|
|
109
|
+
circles: [],
|
|
110
|
+
arcs: [
|
|
111
|
+
...GridDefinitions.reactanceArcs(GridDefinitions.reactanceMajor),
|
|
112
|
+
[
|
|
113
|
+
50,
|
|
114
|
+
[
|
|
115
|
+
[0, 0],
|
|
116
|
+
[0, 1],
|
|
117
|
+
],
|
|
118
|
+
[false, false],
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
-50,
|
|
122
|
+
[
|
|
123
|
+
[0, 1],
|
|
124
|
+
[0, 0],
|
|
125
|
+
],
|
|
126
|
+
[false, true],
|
|
127
|
+
],
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
minor: {
|
|
131
|
+
lines: [],
|
|
132
|
+
circles: [],
|
|
133
|
+
arcs: GridDefinitions.reactanceArcs(GridDefinitions.reactanceMinor),
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { TickDefRequired } from './Tick.js';
|
|
2
|
+
import type { SmithTicksShapes } from './types.js';
|
|
3
|
+
import type { Point } from '../math/geometry.js';
|
|
4
|
+
export type GridKind = 'resistance' | 'reactance' | 'conductance' | 'susceptance';
|
|
5
|
+
export type GridArc = [Point, Point, number, boolean, boolean];
|
|
6
|
+
export declare class GridGeometry {
|
|
7
|
+
private constructor();
|
|
8
|
+
private static readonly calcs;
|
|
9
|
+
private static readonly circles;
|
|
10
|
+
private static readonly clipping;
|
|
11
|
+
/** Normalized geometry only: no DOM, D3, or pixel coordinates. */
|
|
12
|
+
static shapes(kind: GridKind, data: SmithTicksShapes): {
|
|
13
|
+
lines: import("../math/geometry.js").Line[];
|
|
14
|
+
circles: import("../math/geometry.js").Circle[];
|
|
15
|
+
arcs: GridArc[];
|
|
16
|
+
};
|
|
17
|
+
static label(kind: GridKind, definition: TickDefRequired): {
|
|
18
|
+
point: [number, number];
|
|
19
|
+
text: string;
|
|
20
|
+
rotate: number;
|
|
21
|
+
dx: number;
|
|
22
|
+
dy: number;
|
|
23
|
+
textAnchor: string;
|
|
24
|
+
dominantBaseline: string;
|
|
25
|
+
};
|
|
26
|
+
}
|