@smartnet360/svelte-components 0.0.119 → 0.0.121
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/dist/apps/antenna-tools/band-config.d.ts +53 -0
- package/dist/apps/antenna-tools/band-config.js +112 -0
- package/dist/apps/antenna-tools/components/AntennaControls.svelte +558 -0
- package/dist/apps/antenna-tools/components/AntennaControls.svelte.d.ts +16 -0
- package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte +304 -0
- package/dist/apps/antenna-tools/components/AntennaSettingsModal.svelte.d.ts +8 -0
- package/dist/apps/antenna-tools/components/AntennaTools.svelte +597 -0
- package/dist/apps/antenna-tools/components/AntennaTools.svelte.d.ts +42 -0
- package/dist/apps/antenna-tools/components/DatabaseViewer.svelte +278 -0
- package/dist/apps/antenna-tools/components/DatabaseViewer.svelte.d.ts +3 -0
- package/dist/apps/antenna-tools/components/DbNotification.svelte +67 -0
- package/dist/apps/antenna-tools/components/DbNotification.svelte.d.ts +18 -0
- package/dist/apps/antenna-tools/components/JsonImporter.svelte +115 -0
- package/dist/apps/antenna-tools/components/JsonImporter.svelte.d.ts +6 -0
- package/dist/apps/antenna-tools/components/MSIConverter.svelte +282 -0
- package/dist/apps/antenna-tools/components/MSIConverter.svelte.d.ts +6 -0
- package/dist/apps/antenna-tools/components/chart-engines/PolarAreaChart.svelte +123 -0
- package/dist/apps/antenna-tools/components/chart-engines/PolarAreaChart.svelte.d.ts +16 -0
- package/dist/apps/antenna-tools/components/chart-engines/PolarLineChart.svelte +123 -0
- package/dist/apps/antenna-tools/components/chart-engines/PolarLineChart.svelte.d.ts +16 -0
- package/dist/apps/antenna-tools/components/chart-engines/index.d.ts +9 -0
- package/dist/apps/antenna-tools/components/chart-engines/index.js +9 -0
- package/dist/apps/antenna-tools/components/index.d.ts +8 -0
- package/dist/apps/antenna-tools/components/index.js +10 -0
- package/dist/apps/antenna-tools/db.d.ts +28 -0
- package/dist/apps/antenna-tools/db.js +45 -0
- package/dist/apps/antenna-tools/index.d.ts +26 -0
- package/dist/apps/antenna-tools/index.js +40 -0
- package/dist/apps/antenna-tools/stores/antennas.d.ts +13 -0
- package/dist/apps/antenna-tools/stores/antennas.js +25 -0
- package/dist/apps/antenna-tools/stores/db-status.d.ts +32 -0
- package/dist/apps/antenna-tools/stores/db-status.js +38 -0
- package/dist/apps/antenna-tools/stores/index.d.ts +5 -0
- package/dist/apps/antenna-tools/stores/index.js +5 -0
- package/dist/apps/antenna-tools/types.d.ts +137 -0
- package/dist/apps/antenna-tools/types.js +16 -0
- package/dist/apps/antenna-tools/utils/antenna-helpers.d.ts +83 -0
- package/dist/apps/antenna-tools/utils/antenna-helpers.js +198 -0
- package/dist/apps/antenna-tools/utils/chart-engines/index.d.ts +5 -0
- package/dist/apps/antenna-tools/utils/chart-engines/index.js +5 -0
- package/dist/apps/antenna-tools/utils/chart-engines/polar-area-utils.d.ts +94 -0
- package/dist/apps/antenna-tools/utils/chart-engines/polar-area-utils.js +151 -0
- package/dist/apps/antenna-tools/utils/chart-engines/polar-line-utils.d.ts +93 -0
- package/dist/apps/antenna-tools/utils/chart-engines/polar-line-utils.js +139 -0
- package/dist/apps/antenna-tools/utils/db-utils.d.ts +50 -0
- package/dist/apps/antenna-tools/utils/db-utils.js +266 -0
- package/dist/apps/antenna-tools/utils/index.d.ts +7 -0
- package/dist/apps/antenna-tools/utils/index.js +7 -0
- package/dist/apps/antenna-tools/utils/msi-parser.d.ts +21 -0
- package/dist/apps/antenna-tools/utils/msi-parser.js +215 -0
- package/dist/apps/antenna-tools/utils/recent-antennas.d.ts +24 -0
- package/dist/apps/antenna-tools/utils/recent-antennas.js +64 -0
- package/dist/apps/index.d.ts +1 -0
- package/dist/apps/index.js +4 -1
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antenna Tools - Polar Area Chart Utilities
|
|
3
|
+
* Utility functions for creating Plotly polar area charts
|
|
4
|
+
*/
|
|
5
|
+
import type { Antenna } from '../../types';
|
|
6
|
+
export interface PolarAreaTraceData {
|
|
7
|
+
r: number[];
|
|
8
|
+
theta: number[];
|
|
9
|
+
type: 'scatterpolar';
|
|
10
|
+
mode: 'lines';
|
|
11
|
+
fill: 'toself';
|
|
12
|
+
name: string;
|
|
13
|
+
line: {
|
|
14
|
+
color: string;
|
|
15
|
+
width: number;
|
|
16
|
+
};
|
|
17
|
+
fillcolor: string;
|
|
18
|
+
opacity: number;
|
|
19
|
+
hovertemplate?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert antenna pattern to Plotly polar area trace data
|
|
23
|
+
*/
|
|
24
|
+
export declare function convertAntennaPatternToArea(pattern: number[], name: string, baseColor: string, opacity?: number, mechanicalTilt?: number, gainOffset?: number): PolarAreaTraceData;
|
|
25
|
+
/**
|
|
26
|
+
* Get area colors with appropriate transparency
|
|
27
|
+
*/
|
|
28
|
+
export declare function getAreaColors(electricalTilt: number, mechanicalTilt: number, baseColor: string): {
|
|
29
|
+
line: string;
|
|
30
|
+
fill: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Create polar area chart data for antenna patterns
|
|
34
|
+
*/
|
|
35
|
+
export declare function createPolarAreaChartData(selectedAntenna: Antenna | null, selectedAntenna2: Antenna | null, viewMode: 'single' | 'compare', showHorizontalPatterns: boolean, showVerticalPatterns: boolean, ant1ElectricalTilt: number, ant1MechanicalTilt: number, ant2ElectricalTilt: number, ant2MechanicalTilt: number, patternDisplayMode?: 'normalized' | 'gain-adjusted'): PolarAreaTraceData[];
|
|
36
|
+
/**
|
|
37
|
+
* Create Plotly layout for polar area charts
|
|
38
|
+
*/
|
|
39
|
+
export declare function createPolarAreaLayout(title: string): {
|
|
40
|
+
title: {
|
|
41
|
+
text: string;
|
|
42
|
+
font: {
|
|
43
|
+
size: number;
|
|
44
|
+
color: string;
|
|
45
|
+
};
|
|
46
|
+
x: number;
|
|
47
|
+
xanchor: string;
|
|
48
|
+
};
|
|
49
|
+
polar: {
|
|
50
|
+
radialaxis: {
|
|
51
|
+
visible: boolean;
|
|
52
|
+
range: number[];
|
|
53
|
+
tickfont: {
|
|
54
|
+
size: number;
|
|
55
|
+
color: string;
|
|
56
|
+
};
|
|
57
|
+
gridcolor: string;
|
|
58
|
+
linecolor: string;
|
|
59
|
+
tickmode: string;
|
|
60
|
+
tick0: number;
|
|
61
|
+
dtick: number;
|
|
62
|
+
ticksuffix: string;
|
|
63
|
+
};
|
|
64
|
+
angularaxis: {
|
|
65
|
+
visible: boolean;
|
|
66
|
+
tickfont: {
|
|
67
|
+
size: number;
|
|
68
|
+
color: string;
|
|
69
|
+
};
|
|
70
|
+
gridcolor: string;
|
|
71
|
+
linecolor: string;
|
|
72
|
+
direction: string;
|
|
73
|
+
period: number;
|
|
74
|
+
rotation: number;
|
|
75
|
+
ticksuffix: string;
|
|
76
|
+
};
|
|
77
|
+
bgcolor: string;
|
|
78
|
+
};
|
|
79
|
+
margin: {
|
|
80
|
+
t: number;
|
|
81
|
+
r: number;
|
|
82
|
+
b: number;
|
|
83
|
+
l: number;
|
|
84
|
+
};
|
|
85
|
+
height: number;
|
|
86
|
+
paper_bgcolor: string;
|
|
87
|
+
plot_bgcolor: string;
|
|
88
|
+
legend: {
|
|
89
|
+
orientation: string;
|
|
90
|
+
x: number;
|
|
91
|
+
y: number;
|
|
92
|
+
xanchor: string;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antenna Tools - Polar Area Chart Utilities
|
|
3
|
+
* Utility functions for creating Plotly polar area charts
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Convert antenna pattern to Plotly polar area trace data
|
|
7
|
+
*/
|
|
8
|
+
export function convertAntennaPatternToArea(pattern, name, baseColor, opacity = 0.6, mechanicalTilt = 0, gainOffset = 0) {
|
|
9
|
+
// Convert attenuation to dB (negate values) and apply gain offset
|
|
10
|
+
let processedPattern = pattern.map(value => -value + gainOffset);
|
|
11
|
+
// Apply mechanical tilt by shifting the pattern
|
|
12
|
+
if (mechanicalTilt !== 0) {
|
|
13
|
+
const shiftedPattern = new Array(360).fill(0);
|
|
14
|
+
for (let i = 0; i < 360; i++) {
|
|
15
|
+
const sourceIndex = (i - mechanicalTilt + 360) % 360;
|
|
16
|
+
shiftedPattern[i] = processedPattern[sourceIndex] || 0;
|
|
17
|
+
}
|
|
18
|
+
processedPattern = shiftedPattern;
|
|
19
|
+
}
|
|
20
|
+
// Generate theta values (0-359 degrees) with proper rotation
|
|
21
|
+
const theta = [];
|
|
22
|
+
const r = [];
|
|
23
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
24
|
+
let angle = i;
|
|
25
|
+
// Apply rotation to point antenna patterns to 0 degrees (North/up)
|
|
26
|
+
if (name.includes('Vertical')) {
|
|
27
|
+
angle = (i + 0) % 360; // Vertical patterns point to 0° (North/up)
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
angle = (i + 270) % 360; // Rotate horizontal patterns 270° (or -90°) to point North
|
|
31
|
+
}
|
|
32
|
+
theta.push(angle);
|
|
33
|
+
r.push(processedPattern[i]);
|
|
34
|
+
}
|
|
35
|
+
// Close the area by adding the first point at the end
|
|
36
|
+
theta.push(theta[0]);
|
|
37
|
+
r.push(r[0]);
|
|
38
|
+
// Create semi-transparent fill color
|
|
39
|
+
const fillColor = baseColor.replace('rgb', 'rgba').replace(')', `, ${opacity})`);
|
|
40
|
+
return {
|
|
41
|
+
r,
|
|
42
|
+
theta,
|
|
43
|
+
type: 'scatterpolar',
|
|
44
|
+
mode: 'lines',
|
|
45
|
+
fill: 'toself',
|
|
46
|
+
name,
|
|
47
|
+
line: {
|
|
48
|
+
color: baseColor,
|
|
49
|
+
width: 2
|
|
50
|
+
},
|
|
51
|
+
fillcolor: fillColor,
|
|
52
|
+
opacity: 1, // Set to 1 since we control opacity via fillcolor
|
|
53
|
+
hovertemplate: '%{theta} <br>%{r:.2f} dB<extra></extra>'
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get area colors with appropriate transparency
|
|
58
|
+
*/
|
|
59
|
+
export function getAreaColors(electricalTilt, mechanicalTilt, baseColor) {
|
|
60
|
+
return {
|
|
61
|
+
line: baseColor,
|
|
62
|
+
fill: baseColor.replace('rgb', 'rgba').replace(')', ', 0.3)')
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create polar area chart data for antenna patterns
|
|
67
|
+
*/
|
|
68
|
+
export function createPolarAreaChartData(selectedAntenna, selectedAntenna2, viewMode, showHorizontalPatterns, showVerticalPatterns, ant1ElectricalTilt, ant1MechanicalTilt, ant2ElectricalTilt, ant2MechanicalTilt, patternDisplayMode = 'normalized') {
|
|
69
|
+
const data = [];
|
|
70
|
+
// Calculate gain offsets for gain-adjusted display mode
|
|
71
|
+
let ant1GainOffset = 0;
|
|
72
|
+
let ant2GainOffset = 0;
|
|
73
|
+
if (patternDisplayMode === 'gain-adjusted' && viewMode === 'compare') {
|
|
74
|
+
const ant1Gain = selectedAntenna?.gain_dBd || 0;
|
|
75
|
+
const ant2Gain = selectedAntenna2?.gain_dBd || 0;
|
|
76
|
+
const maxGain = Math.max(ant1Gain, ant2Gain);
|
|
77
|
+
// Offset both antennas relative to the highest gain antenna
|
|
78
|
+
ant1GainOffset = ant1Gain - maxGain;
|
|
79
|
+
ant2GainOffset = ant2Gain - maxGain;
|
|
80
|
+
}
|
|
81
|
+
// Create antenna 1 pattern data based on visibility settings
|
|
82
|
+
if (selectedAntenna) {
|
|
83
|
+
if (showHorizontalPatterns) {
|
|
84
|
+
const horizontalData1 = convertAntennaPatternToArea(selectedAntenna.pattern || [], 'Antenna 1 - Horizontal', 'rgb(0, 102, 204)', 0.4, ant1MechanicalTilt, ant1GainOffset);
|
|
85
|
+
data.push(horizontalData1);
|
|
86
|
+
}
|
|
87
|
+
if (showVerticalPatterns) {
|
|
88
|
+
const verticalData1 = convertAntennaPatternToArea(selectedAntenna.vertical_pattern || [], 'Antenna 1 - Vertical', 'rgb(0, 61, 122)', 0.3, ant1MechanicalTilt, ant1GainOffset);
|
|
89
|
+
data.push(verticalData1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Add second antenna if in compare mode and antenna 2 is selected
|
|
93
|
+
if (viewMode === 'compare' && selectedAntenna2) {
|
|
94
|
+
if (showHorizontalPatterns) {
|
|
95
|
+
const horizontalData2 = convertAntennaPatternToArea(selectedAntenna2.pattern || [], 'Antenna 2 - Horizontal', 'rgb(255, 215, 0)', 0.4, ant2MechanicalTilt, ant2GainOffset);
|
|
96
|
+
data.push(horizontalData2);
|
|
97
|
+
}
|
|
98
|
+
if (showVerticalPatterns) {
|
|
99
|
+
const verticalData2 = convertAntennaPatternToArea(selectedAntenna2.vertical_pattern || [], 'Antenna 2 - Vertical', 'rgb(230, 194, 0)', 0.3, ant2MechanicalTilt, ant2GainOffset);
|
|
100
|
+
data.push(verticalData2);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return data;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Create Plotly layout for polar area charts
|
|
107
|
+
*/
|
|
108
|
+
export function createPolarAreaLayout(title) {
|
|
109
|
+
return {
|
|
110
|
+
title: {
|
|
111
|
+
text: title,
|
|
112
|
+
font: { size: 16, color: '#212529' },
|
|
113
|
+
x: 0.5,
|
|
114
|
+
xanchor: 'center'
|
|
115
|
+
},
|
|
116
|
+
polar: {
|
|
117
|
+
radialaxis: {
|
|
118
|
+
visible: true,
|
|
119
|
+
range: [-70, 0],
|
|
120
|
+
tickfont: { size: 10, color: '#6c757d' },
|
|
121
|
+
gridcolor: 'rgba(108, 117, 125, 0.3)',
|
|
122
|
+
linecolor: 'rgba(108, 117, 125, 0.5)',
|
|
123
|
+
tickmode: 'linear',
|
|
124
|
+
tick0: -70,
|
|
125
|
+
dtick: 10,
|
|
126
|
+
ticksuffix: ' dB'
|
|
127
|
+
},
|
|
128
|
+
angularaxis: {
|
|
129
|
+
visible: true,
|
|
130
|
+
tickfont: { size: 11, color: '#495057' },
|
|
131
|
+
gridcolor: 'rgba(108, 117, 125, 0.2)',
|
|
132
|
+
linecolor: 'rgba(108, 117, 125, 0.4)',
|
|
133
|
+
direction: 'clockwise',
|
|
134
|
+
period: 360,
|
|
135
|
+
rotation: 0,
|
|
136
|
+
ticksuffix: '°'
|
|
137
|
+
},
|
|
138
|
+
bgcolor: 'rgba(248, 249, 250, 0.5)'
|
|
139
|
+
},
|
|
140
|
+
margin: { t: 60, r: 40, b: 60, l: 40 },
|
|
141
|
+
height: 600,
|
|
142
|
+
paper_bgcolor: 'rgba(255, 255, 255, 0.95)',
|
|
143
|
+
plot_bgcolor: 'rgba(248, 249, 250, 0.3)',
|
|
144
|
+
legend: {
|
|
145
|
+
orientation: 'h',
|
|
146
|
+
x: 0.5,
|
|
147
|
+
y: -0.1,
|
|
148
|
+
xanchor: 'center'
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antenna Tools - Polar Line Chart Utilities
|
|
3
|
+
* Utility functions for creating Plotly polar line charts
|
|
4
|
+
*/
|
|
5
|
+
import type { Antenna } from '../../types';
|
|
6
|
+
export interface PolarLineTraceData {
|
|
7
|
+
r: number[];
|
|
8
|
+
theta: number[];
|
|
9
|
+
type: 'scatterpolar';
|
|
10
|
+
mode: 'lines';
|
|
11
|
+
name: string;
|
|
12
|
+
line: {
|
|
13
|
+
color: string;
|
|
14
|
+
width: number;
|
|
15
|
+
dash: string;
|
|
16
|
+
};
|
|
17
|
+
hovertemplate?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Convert antenna pattern to Plotly polar line trace data
|
|
21
|
+
*/
|
|
22
|
+
export declare function convertAntennaPatternToLine(pattern: number[], name: string, color: string, width?: number, mechanicalTilt?: number, gainOffset?: number): PolarLineTraceData;
|
|
23
|
+
/**
|
|
24
|
+
* Get fixed line color (no dynamic changes)
|
|
25
|
+
*/
|
|
26
|
+
export declare function getLineColor(electricalTilt: number, mechanicalTilt: number, baseColor: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Get fixed line width (no dynamic changes)
|
|
29
|
+
*/
|
|
30
|
+
export declare function getLineWidth(electricalTilt: number, mechanicalTilt: number): number;
|
|
31
|
+
/**
|
|
32
|
+
* Create polar line chart data for antenna patterns
|
|
33
|
+
*/
|
|
34
|
+
export declare function createPolarLineChartData(selectedAntenna: Antenna | null, selectedAntenna2: Antenna | null, viewMode: 'single' | 'compare', showHorizontalPatterns: boolean, showVerticalPatterns: boolean, ant1ElectricalTilt: number, ant1MechanicalTilt: number, ant2ElectricalTilt: number, ant2MechanicalTilt: number, patternDisplayMode?: 'normalized' | 'gain-adjusted'): PolarLineTraceData[];
|
|
35
|
+
/**
|
|
36
|
+
* Create Plotly layout for polar line charts
|
|
37
|
+
*/
|
|
38
|
+
export declare function createPolarLineLayout(title: string): {
|
|
39
|
+
title: {
|
|
40
|
+
text: string;
|
|
41
|
+
font: {
|
|
42
|
+
size: number;
|
|
43
|
+
color: string;
|
|
44
|
+
};
|
|
45
|
+
x: number;
|
|
46
|
+
xanchor: string;
|
|
47
|
+
};
|
|
48
|
+
polar: {
|
|
49
|
+
radialaxis: {
|
|
50
|
+
visible: boolean;
|
|
51
|
+
range: number[];
|
|
52
|
+
tickfont: {
|
|
53
|
+
size: number;
|
|
54
|
+
color: string;
|
|
55
|
+
};
|
|
56
|
+
gridcolor: string;
|
|
57
|
+
linecolor: string;
|
|
58
|
+
tickmode: string;
|
|
59
|
+
tick0: number;
|
|
60
|
+
dtick: number;
|
|
61
|
+
ticksuffix: string;
|
|
62
|
+
};
|
|
63
|
+
angularaxis: {
|
|
64
|
+
visible: boolean;
|
|
65
|
+
tickfont: {
|
|
66
|
+
size: number;
|
|
67
|
+
color: string;
|
|
68
|
+
};
|
|
69
|
+
gridcolor: string;
|
|
70
|
+
linecolor: string;
|
|
71
|
+
direction: string;
|
|
72
|
+
period: number;
|
|
73
|
+
rotation: number;
|
|
74
|
+
ticksuffix: string;
|
|
75
|
+
};
|
|
76
|
+
bgcolor: string;
|
|
77
|
+
};
|
|
78
|
+
margin: {
|
|
79
|
+
t: number;
|
|
80
|
+
r: number;
|
|
81
|
+
b: number;
|
|
82
|
+
l: number;
|
|
83
|
+
};
|
|
84
|
+
height: number;
|
|
85
|
+
paper_bgcolor: string;
|
|
86
|
+
plot_bgcolor: string;
|
|
87
|
+
legend: {
|
|
88
|
+
orientation: string;
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
xanchor: string;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antenna Tools - Polar Line Chart Utilities
|
|
3
|
+
* Utility functions for creating Plotly polar line charts
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Convert antenna pattern to Plotly polar line trace data
|
|
7
|
+
*/
|
|
8
|
+
export function convertAntennaPatternToLine(pattern, name, color, width = 2, mechanicalTilt = 0, gainOffset = 0) {
|
|
9
|
+
// Convert attenuation to dB (negate values) and apply gain offset
|
|
10
|
+
let processedPattern = pattern.map(value => -value + gainOffset);
|
|
11
|
+
// Apply mechanical tilt by shifting the pattern
|
|
12
|
+
if (mechanicalTilt !== 0) {
|
|
13
|
+
const shiftedPattern = new Array(360).fill(0);
|
|
14
|
+
for (let i = 0; i < 360; i++) {
|
|
15
|
+
const sourceIndex = (i - mechanicalTilt + 360) % 360;
|
|
16
|
+
shiftedPattern[i] = processedPattern[sourceIndex] || 0;
|
|
17
|
+
}
|
|
18
|
+
processedPattern = shiftedPattern;
|
|
19
|
+
}
|
|
20
|
+
// Generate theta values (0-359 degrees) with proper rotation to point to 0 degrees
|
|
21
|
+
const theta = Array.from({ length: pattern.length }, (_, i) => {
|
|
22
|
+
if (name.includes('Vertical')) {
|
|
23
|
+
return (i + 0) % 360; // Vertical patterns point to 0° (North/up)
|
|
24
|
+
}
|
|
25
|
+
return (i + 270) % 360; // Rotate horizontal patterns 270° (or -90°) to point North
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
r: processedPattern,
|
|
29
|
+
theta,
|
|
30
|
+
type: 'scatterpolar',
|
|
31
|
+
mode: 'lines',
|
|
32
|
+
name,
|
|
33
|
+
line: {
|
|
34
|
+
color,
|
|
35
|
+
width,
|
|
36
|
+
dash: 'solid' // Always solid lines
|
|
37
|
+
},
|
|
38
|
+
hovertemplate: '%{theta} <br>%{r:.2f} dB<extra></extra>'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get fixed line color (no dynamic changes)
|
|
43
|
+
*/
|
|
44
|
+
export function getLineColor(electricalTilt, mechanicalTilt, baseColor) {
|
|
45
|
+
return baseColor; // Always return base color
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get fixed line width (no dynamic changes)
|
|
49
|
+
*/
|
|
50
|
+
export function getLineWidth(electricalTilt, mechanicalTilt) {
|
|
51
|
+
return 2; // Always return fixed width
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create polar line chart data for antenna patterns
|
|
55
|
+
*/
|
|
56
|
+
export function createPolarLineChartData(selectedAntenna, selectedAntenna2, viewMode, showHorizontalPatterns, showVerticalPatterns, ant1ElectricalTilt, ant1MechanicalTilt, ant2ElectricalTilt, ant2MechanicalTilt, patternDisplayMode = 'normalized') {
|
|
57
|
+
const data = [];
|
|
58
|
+
// Calculate gain offsets for gain-adjusted display mode
|
|
59
|
+
let ant1GainOffset = 0;
|
|
60
|
+
let ant2GainOffset = 0;
|
|
61
|
+
if (patternDisplayMode === 'gain-adjusted' && viewMode === 'compare') {
|
|
62
|
+
const ant1Gain = selectedAntenna?.gain_dBd || 0;
|
|
63
|
+
const ant2Gain = selectedAntenna2?.gain_dBd || 0;
|
|
64
|
+
const maxGain = Math.max(ant1Gain, ant2Gain);
|
|
65
|
+
// Offset both antennas relative to the highest gain antenna
|
|
66
|
+
ant1GainOffset = ant1Gain - maxGain;
|
|
67
|
+
ant2GainOffset = ant2Gain - maxGain;
|
|
68
|
+
}
|
|
69
|
+
// Create antenna 1 pattern data based on visibility settings
|
|
70
|
+
if (selectedAntenna) {
|
|
71
|
+
if (showHorizontalPatterns) {
|
|
72
|
+
const horizontalData1 = convertAntennaPatternToLine(selectedAntenna.pattern || [], 'Antenna 1 - Horizontal', getLineColor(ant1ElectricalTilt, ant1MechanicalTilt, '#0066cc'), getLineWidth(ant1ElectricalTilt, ant1MechanicalTilt), ant1MechanicalTilt, ant1GainOffset);
|
|
73
|
+
data.push(horizontalData1);
|
|
74
|
+
}
|
|
75
|
+
if (showVerticalPatterns) {
|
|
76
|
+
const verticalData1 = convertAntennaPatternToLine(selectedAntenna.vertical_pattern || [], 'Antenna 1 - Vertical', getLineColor(ant1ElectricalTilt, ant1MechanicalTilt, '#003d7a'), getLineWidth(ant1ElectricalTilt, ant1MechanicalTilt), ant1MechanicalTilt, ant1GainOffset);
|
|
77
|
+
data.push(verticalData1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Add second antenna if in compare mode and antenna 2 is selected
|
|
81
|
+
if (viewMode === 'compare' && selectedAntenna2) {
|
|
82
|
+
if (showHorizontalPatterns) {
|
|
83
|
+
const horizontalData2 = convertAntennaPatternToLine(selectedAntenna2.pattern || [], 'Antenna 2 - Horizontal', getLineColor(ant2ElectricalTilt, ant2MechanicalTilt, '#ffd700'), getLineWidth(ant2ElectricalTilt, ant2MechanicalTilt), ant2MechanicalTilt, ant2GainOffset);
|
|
84
|
+
data.push(horizontalData2);
|
|
85
|
+
}
|
|
86
|
+
if (showVerticalPatterns) {
|
|
87
|
+
const verticalData2 = convertAntennaPatternToLine(selectedAntenna2.vertical_pattern || [], 'Antenna 2 - Vertical', getLineColor(ant2ElectricalTilt, ant2MechanicalTilt, '#e6c200'), getLineWidth(ant2ElectricalTilt, ant2MechanicalTilt), ant2MechanicalTilt, ant2GainOffset);
|
|
88
|
+
data.push(verticalData2);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return data;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Create Plotly layout for polar line charts
|
|
95
|
+
*/
|
|
96
|
+
export function createPolarLineLayout(title) {
|
|
97
|
+
return {
|
|
98
|
+
title: {
|
|
99
|
+
text: title,
|
|
100
|
+
font: { size: 16, color: '#212529' },
|
|
101
|
+
x: 0.5,
|
|
102
|
+
xanchor: 'center'
|
|
103
|
+
},
|
|
104
|
+
polar: {
|
|
105
|
+
radialaxis: {
|
|
106
|
+
visible: true,
|
|
107
|
+
range: [-70, 0],
|
|
108
|
+
tickfont: { size: 10, color: '#6c757d' },
|
|
109
|
+
gridcolor: 'rgba(108, 117, 125, 0.3)',
|
|
110
|
+
linecolor: 'rgba(108, 117, 125, 0.5)',
|
|
111
|
+
tickmode: 'linear',
|
|
112
|
+
tick0: -70,
|
|
113
|
+
dtick: 10,
|
|
114
|
+
ticksuffix: ' dB'
|
|
115
|
+
},
|
|
116
|
+
angularaxis: {
|
|
117
|
+
visible: true,
|
|
118
|
+
tickfont: { size: 11, color: '#495057' },
|
|
119
|
+
gridcolor: 'rgba(108, 117, 125, 0.2)',
|
|
120
|
+
linecolor: 'rgba(108, 117, 125, 0.4)',
|
|
121
|
+
direction: 'clockwise',
|
|
122
|
+
period: 360,
|
|
123
|
+
rotation: 0,
|
|
124
|
+
ticksuffix: '°'
|
|
125
|
+
},
|
|
126
|
+
bgcolor: 'rgba(248, 249, 250, 0.5)'
|
|
127
|
+
},
|
|
128
|
+
margin: { t: 60, r: 40, b: 60, l: 40 },
|
|
129
|
+
height: 600,
|
|
130
|
+
paper_bgcolor: 'rgba(255, 255, 255, 0.95)',
|
|
131
|
+
plot_bgcolor: 'rgba(248, 249, 250, 0.3)',
|
|
132
|
+
legend: {
|
|
133
|
+
orientation: 'h',
|
|
134
|
+
x: 0.5,
|
|
135
|
+
y: -0.1,
|
|
136
|
+
xanchor: 'center'
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antenna Tools - Database Utilities
|
|
3
|
+
* CRUD operations for antenna data with automatic purge on import
|
|
4
|
+
*/
|
|
5
|
+
import type { Antenna, RawAntenna } from '../types';
|
|
6
|
+
import { type PurgeStats } from '../band-config';
|
|
7
|
+
/**
|
|
8
|
+
* Load all antennas from database
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadAntennas(): Promise<Antenna[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Import result with purge statistics
|
|
13
|
+
*/
|
|
14
|
+
export interface ImportResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
purgeStats: PurgeStats;
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Save raw antennas to database with automatic purge
|
|
21
|
+
*
|
|
22
|
+
* This is the main import function:
|
|
23
|
+
* 1. Takes raw antennas (with actual MHz frequencies)
|
|
24
|
+
* 2. Purges to keep only one per band (closest to center)
|
|
25
|
+
* 3. Saves purged antennas to database
|
|
26
|
+
*
|
|
27
|
+
* @param rawAntennas - Antennas parsed from MSI files
|
|
28
|
+
* @returns Import result with purge statistics
|
|
29
|
+
*/
|
|
30
|
+
export declare function saveAntennasWithPurge(rawAntennas: RawAntenna[]): Promise<ImportResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Save antennas directly (without purge) - for pre-purged data
|
|
33
|
+
*/
|
|
34
|
+
export declare function saveAntennas(antennaData: Antenna[]): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Import from JSON file (expects pre-purged data)
|
|
37
|
+
*/
|
|
38
|
+
export declare function importFromJson(jsonFile: File): Promise<Antenna[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Export all antennas to JSON file download
|
|
41
|
+
*/
|
|
42
|
+
export declare function exportAntennas(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Clear all antenna data from database
|
|
45
|
+
*/
|
|
46
|
+
export declare function clearAllAntennas(): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Check if data has been imported before
|
|
49
|
+
*/
|
|
50
|
+
export declare function hasImportedData(): boolean;
|