@smartnet360/svelte-components 0.0.13 → 0.0.14
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-pattern/components/AntennaControls.svelte +38 -48
- package/dist/apps/antenna-pattern/components/AntennaDiagrams.svelte +138 -96
- package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte +125 -0
- package/dist/apps/antenna-pattern/components/chart-engines/PolarAreaChart.svelte.d.ts +16 -0
- package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte +121 -0
- package/dist/apps/antenna-pattern/components/chart-engines/PolarBarChart.svelte.d.ts +15 -0
- package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte +125 -0
- package/dist/apps/antenna-pattern/components/chart-engines/PolarLineChart.svelte.d.ts +16 -0
- package/dist/apps/antenna-pattern/components/chart-engines/index.d.ts +9 -0
- package/dist/apps/antenna-pattern/components/chart-engines/index.js +8 -0
- package/dist/apps/antenna-pattern/index.d.ts +1 -0
- package/dist/apps/antenna-pattern/index.js +2 -0
- package/dist/apps/antenna-pattern/utils/chart-engines/polar-area-utils.d.ts +89 -0
- package/dist/apps/antenna-pattern/utils/chart-engines/polar-area-utils.js +146 -0
- package/dist/apps/antenna-pattern/utils/chart-engines/polar-bar-utils.d.ts +88 -0
- package/dist/apps/antenna-pattern/utils/chart-engines/polar-bar-utils.js +131 -0
- package/dist/apps/antenna-pattern/utils/chart-engines/polar-line-utils.d.ts +88 -0
- package/dist/apps/antenna-pattern/utils/chart-engines/polar-line-utils.js +134 -0
- package/dist/apps/antenna-pattern/utils/recent-antennas.d.ts +20 -0
- package/dist/apps/antenna-pattern/utils/recent-antennas.js +60 -0
- package/package.json +1 -1
@@ -0,0 +1,121 @@
|
|
1
|
+
<svelte:options runes={true} />
|
2
|
+
|
3
|
+
<script lang="ts">
|
4
|
+
import { onMount } from 'svelte';
|
5
|
+
import { browser } from '$app/environment';
|
6
|
+
import type { Antenna } from '../../db';
|
7
|
+
import {
|
8
|
+
createPolarBarChartData,
|
9
|
+
createPolarBarLayout,
|
10
|
+
type PolarBarTraceData
|
11
|
+
} from '../../utils/chart-engines/polar-bar-utils';
|
12
|
+
|
13
|
+
interface Props {
|
14
|
+
selectedAntenna?: Antenna | null;
|
15
|
+
selectedAntenna2?: Antenna | null;
|
16
|
+
viewMode?: 'single' | 'compare';
|
17
|
+
patternType?: 'horizontal' | 'vertical';
|
18
|
+
ant1ElectricalTilt?: number;
|
19
|
+
ant1MechanicalTilt?: number;
|
20
|
+
ant2ElectricalTilt?: number;
|
21
|
+
ant2MechanicalTilt?: number;
|
22
|
+
title?: string;
|
23
|
+
}
|
24
|
+
|
25
|
+
let {
|
26
|
+
selectedAntenna = null,
|
27
|
+
selectedAntenna2 = null,
|
28
|
+
viewMode = 'single',
|
29
|
+
patternType = 'vertical',
|
30
|
+
ant1ElectricalTilt = 0,
|
31
|
+
ant1MechanicalTilt = 0,
|
32
|
+
ant2ElectricalTilt = 0,
|
33
|
+
ant2MechanicalTilt = 0,
|
34
|
+
title = 'Antenna Pattern - Polar Bar Chart'
|
35
|
+
}: Props = $props();
|
36
|
+
|
37
|
+
let Plotly: any;
|
38
|
+
let chartDiv = $state<HTMLDivElement>();
|
39
|
+
let chartInitialized = $state(false);
|
40
|
+
|
41
|
+
// Initialize Plotly on mount
|
42
|
+
onMount(async () => {
|
43
|
+
if (browser) {
|
44
|
+
try {
|
45
|
+
Plotly = await import('plotly.js-dist-min');
|
46
|
+
console.log('Plotly loaded for polar bar chart');
|
47
|
+
await initializeChart();
|
48
|
+
} catch (error) {
|
49
|
+
console.error('Failed to load Plotly:', error);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
});
|
53
|
+
|
54
|
+
// Update chart when data changes
|
55
|
+
$effect(() => {
|
56
|
+
if (chartInitialized) {
|
57
|
+
updateChart();
|
58
|
+
}
|
59
|
+
});
|
60
|
+
|
61
|
+
async function initializeChart() {
|
62
|
+
if (!Plotly || !chartDiv) return;
|
63
|
+
|
64
|
+
const data = createPolarBarChartData(
|
65
|
+
selectedAntenna,
|
66
|
+
selectedAntenna2,
|
67
|
+
viewMode,
|
68
|
+
patternType === 'horizontal',
|
69
|
+
patternType === 'vertical',
|
70
|
+
ant1ElectricalTilt,
|
71
|
+
ant1MechanicalTilt,
|
72
|
+
ant2ElectricalTilt,
|
73
|
+
ant2MechanicalTilt
|
74
|
+
);
|
75
|
+
|
76
|
+
const layout = createPolarBarLayout(title);
|
77
|
+
const config = {
|
78
|
+
responsive: true,
|
79
|
+
displayModeBar: true,
|
80
|
+
displaylogo: false,
|
81
|
+
modeBarButtonsToRemove: [
|
82
|
+
'zoom2d', 'pan2d', 'select2d', 'lasso2d',
|
83
|
+
'zoomIn2d', 'zoomOut2d', 'autoScale2d',
|
84
|
+
'resetScale2d', 'toggleSpikelines', 'toImage'
|
85
|
+
]
|
86
|
+
};
|
87
|
+
|
88
|
+
try {
|
89
|
+
await Plotly.newPlot(chartDiv, data, layout, config);
|
90
|
+
chartInitialized = true;
|
91
|
+
console.log('Polar bar chart initialized');
|
92
|
+
} catch (error) {
|
93
|
+
console.error('Failed to create polar bar chart:', error);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
async function updateChart() {
|
98
|
+
if (!Plotly || !chartDiv || !chartInitialized) return;
|
99
|
+
|
100
|
+
try {
|
101
|
+
const data = createPolarBarChartData(
|
102
|
+
selectedAntenna,
|
103
|
+
selectedAntenna2,
|
104
|
+
viewMode,
|
105
|
+
patternType === 'horizontal',
|
106
|
+
patternType === 'vertical',
|
107
|
+
ant1ElectricalTilt,
|
108
|
+
ant1MechanicalTilt,
|
109
|
+
ant2ElectricalTilt,
|
110
|
+
ant2MechanicalTilt
|
111
|
+
);
|
112
|
+
|
113
|
+
const layout = createPolarBarLayout(title);
|
114
|
+
await Plotly.react(chartDiv, data, layout);
|
115
|
+
} catch (error) {
|
116
|
+
console.error('Failed to update polar bar chart:', error);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
</script>
|
120
|
+
|
121
|
+
<div bind:this={chartDiv} style="height: 700px;"></div>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import type { Antenna } from '../../db';
|
2
|
+
interface Props {
|
3
|
+
selectedAntenna?: Antenna | null;
|
4
|
+
selectedAntenna2?: Antenna | null;
|
5
|
+
viewMode?: 'single' | 'compare';
|
6
|
+
patternType?: 'horizontal' | 'vertical';
|
7
|
+
ant1ElectricalTilt?: number;
|
8
|
+
ant1MechanicalTilt?: number;
|
9
|
+
ant2ElectricalTilt?: number;
|
10
|
+
ant2MechanicalTilt?: number;
|
11
|
+
title?: string;
|
12
|
+
}
|
13
|
+
declare const PolarBarChart: import("svelte").Component<Props, {}, "">;
|
14
|
+
type PolarBarChart = ReturnType<typeof PolarBarChart>;
|
15
|
+
export default PolarBarChart;
|
@@ -0,0 +1,125 @@
|
|
1
|
+
<svelte:options runes={true} />
|
2
|
+
|
3
|
+
<script lang="ts">
|
4
|
+
import { onMount } from 'svelte';
|
5
|
+
import { browser } from '$app/environment';
|
6
|
+
import type { Antenna } from '../../db';
|
7
|
+
import {
|
8
|
+
createPolarLineChartData,
|
9
|
+
createPolarLineLayout,
|
10
|
+
type PolarLineTraceData
|
11
|
+
} from '../../utils/chart-engines/polar-line-utils';
|
12
|
+
|
13
|
+
interface Props {
|
14
|
+
selectedAntenna?: Antenna | null;
|
15
|
+
selectedAntenna2?: Antenna | null;
|
16
|
+
viewMode?: 'single' | 'compare';
|
17
|
+
patternType?: 'horizontal' | 'vertical';
|
18
|
+
patternDisplayMode?: 'normalized' | 'gain-adjusted';
|
19
|
+
ant1ElectricalTilt?: number;
|
20
|
+
ant1MechanicalTilt?: number;
|
21
|
+
ant2ElectricalTilt?: number;
|
22
|
+
ant2MechanicalTilt?: number;
|
23
|
+
title?: string;
|
24
|
+
}
|
25
|
+
|
26
|
+
let {
|
27
|
+
selectedAntenna = null,
|
28
|
+
selectedAntenna2 = null,
|
29
|
+
viewMode = 'single',
|
30
|
+
patternType = 'vertical',
|
31
|
+
patternDisplayMode = 'normalized',
|
32
|
+
ant1ElectricalTilt = 0,
|
33
|
+
ant1MechanicalTilt = 0,
|
34
|
+
ant2ElectricalTilt = 0,
|
35
|
+
ant2MechanicalTilt = 0,
|
36
|
+
title = 'Antenna Pattern - Polar Line Chart'
|
37
|
+
}: Props = $props();
|
38
|
+
|
39
|
+
let Plotly: any;
|
40
|
+
let chartDiv = $state<HTMLDivElement>();
|
41
|
+
let chartInitialized = $state(false);
|
42
|
+
|
43
|
+
// Initialize Plotly on mount
|
44
|
+
onMount(async () => {
|
45
|
+
if (browser) {
|
46
|
+
try {
|
47
|
+
Plotly = await import('plotly.js-dist-min');
|
48
|
+
console.log('Plotly loaded for polar line chart');
|
49
|
+
await initializeChart();
|
50
|
+
} catch (error) {
|
51
|
+
console.error('Failed to load Plotly:', error);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
});
|
55
|
+
|
56
|
+
// Update chart when data changes
|
57
|
+
$effect(() => {
|
58
|
+
if (chartInitialized) {
|
59
|
+
updateChart();
|
60
|
+
}
|
61
|
+
});
|
62
|
+
|
63
|
+
async function initializeChart() {
|
64
|
+
if (!Plotly || !chartDiv) return;
|
65
|
+
|
66
|
+
const data = createPolarLineChartData(
|
67
|
+
selectedAntenna,
|
68
|
+
selectedAntenna2,
|
69
|
+
viewMode,
|
70
|
+
patternType === 'horizontal',
|
71
|
+
patternType === 'vertical',
|
72
|
+
ant1ElectricalTilt,
|
73
|
+
ant1MechanicalTilt,
|
74
|
+
ant2ElectricalTilt,
|
75
|
+
ant2MechanicalTilt,
|
76
|
+
patternDisplayMode
|
77
|
+
);
|
78
|
+
|
79
|
+
const layout = createPolarLineLayout(title);
|
80
|
+
const config = {
|
81
|
+
responsive: true,
|
82
|
+
displayModeBar: true,
|
83
|
+
displaylogo: false,
|
84
|
+
modeBarButtonsToRemove: [
|
85
|
+
'zoom2d', 'pan2d', 'select2d', 'lasso2d',
|
86
|
+
'zoomIn2d', 'zoomOut2d', 'autoScale2d',
|
87
|
+
'resetScale2d', 'toggleSpikelines', 'toImage'
|
88
|
+
]
|
89
|
+
};
|
90
|
+
|
91
|
+
try {
|
92
|
+
await Plotly.newPlot(chartDiv, data, layout, config);
|
93
|
+
chartInitialized = true;
|
94
|
+
console.log('Polar line chart initialized');
|
95
|
+
} catch (error) {
|
96
|
+
console.error('Failed to create polar line chart:', error);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
async function updateChart() {
|
101
|
+
if (!Plotly || !chartDiv || !chartInitialized) return;
|
102
|
+
|
103
|
+
try {
|
104
|
+
const data = createPolarLineChartData(
|
105
|
+
selectedAntenna,
|
106
|
+
selectedAntenna2,
|
107
|
+
viewMode,
|
108
|
+
patternType === 'horizontal',
|
109
|
+
patternType === 'vertical',
|
110
|
+
ant1ElectricalTilt,
|
111
|
+
ant1MechanicalTilt,
|
112
|
+
ant2ElectricalTilt,
|
113
|
+
ant2MechanicalTilt,
|
114
|
+
patternDisplayMode
|
115
|
+
);
|
116
|
+
|
117
|
+
const layout = createPolarLineLayout(title);
|
118
|
+
await Plotly.react(chartDiv, data, layout);
|
119
|
+
} catch (error) {
|
120
|
+
console.error('Failed to update polar line chart:', error);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
</script>
|
124
|
+
|
125
|
+
<div bind:this={chartDiv} style="height: 700px;"></div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import type { Antenna } from '../../db';
|
2
|
+
interface Props {
|
3
|
+
selectedAntenna?: Antenna | null;
|
4
|
+
selectedAntenna2?: Antenna | null;
|
5
|
+
viewMode?: 'single' | 'compare';
|
6
|
+
patternType?: 'horizontal' | 'vertical';
|
7
|
+
patternDisplayMode?: 'normalized' | 'gain-adjusted';
|
8
|
+
ant1ElectricalTilt?: number;
|
9
|
+
ant1MechanicalTilt?: number;
|
10
|
+
ant2ElectricalTilt?: number;
|
11
|
+
ant2MechanicalTilt?: number;
|
12
|
+
title?: string;
|
13
|
+
}
|
14
|
+
declare const PolarLineChart: import("svelte").Component<Props, {}, "">;
|
15
|
+
type PolarLineChart = ReturnType<typeof PolarLineChart>;
|
16
|
+
export default PolarLineChart;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
export { default as PolarLineChart } from './PolarLineChart.svelte';
|
2
|
+
export { default as PolarBarChart } from './PolarBarChart.svelte';
|
3
|
+
export { default as PolarAreaChart } from './PolarAreaChart.svelte';
|
4
|
+
export type { PolarLineTraceData } from '../../utils/chart-engines/polar-line-utils';
|
5
|
+
export type { PolarBarTraceData } from '../../utils/chart-engines/polar-bar-utils';
|
6
|
+
export type { PolarAreaTraceData } from '../../utils/chart-engines/polar-area-utils';
|
7
|
+
export * from '../../utils/chart-engines/polar-line-utils';
|
8
|
+
export * from '../../utils/chart-engines/polar-bar-utils';
|
9
|
+
export * from '../../utils/chart-engines/polar-area-utils';
|
@@ -0,0 +1,8 @@
|
|
1
|
+
// Chart Engine Components
|
2
|
+
export { default as PolarLineChart } from './PolarLineChart.svelte';
|
3
|
+
export { default as PolarBarChart } from './PolarBarChart.svelte';
|
4
|
+
export { default as PolarAreaChart } from './PolarAreaChart.svelte';
|
5
|
+
// Chart Engine Utilities
|
6
|
+
export * from '../../utils/chart-engines/polar-line-utils';
|
7
|
+
export * from '../../utils/chart-engines/polar-bar-utils';
|
8
|
+
export * from '../../utils/chart-engines/polar-area-utils';
|
@@ -6,6 +6,7 @@ export { default as JsonImporter } from './components/JsonImporter.svelte';
|
|
6
6
|
export { default as MSIConverter } from './components/MSIConverter.svelte';
|
7
7
|
export { default as DbNotification } from './components/DbNotification.svelte';
|
8
8
|
export { default as AntennaDataDropdown } from './components/AntennaDataDropdown.svelte';
|
9
|
+
export { PolarLineChart, PolarBarChart } from './components/chart-engines/index';
|
9
10
|
export { antennas, selectedAntenna, searchQuery, filteredAntennas } from './stores/antennas';
|
10
11
|
export { dbStatus, dataOperationStatus, updateDbStatus, trackDataOperation } from './stores/db-status';
|
11
12
|
export { db, type Antenna } from './db';
|
@@ -7,6 +7,8 @@ export { default as JsonImporter } from './components/JsonImporter.svelte';
|
|
7
7
|
export { default as MSIConverter } from './components/MSIConverter.svelte';
|
8
8
|
export { default as DbNotification } from './components/DbNotification.svelte';
|
9
9
|
export { default as AntennaDataDropdown } from './components/AntennaDataDropdown.svelte';
|
10
|
+
// Chart Engine Components
|
11
|
+
export { PolarLineChart, PolarBarChart } from './components/chart-engines/index';
|
10
12
|
// Stores
|
11
13
|
export { antennas, selectedAntenna, searchQuery, filteredAntennas } from './stores/antennas';
|
12
14
|
export { dbStatus, dataOperationStatus, updateDbStatus, trackDataOperation } from './stores/db-status';
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import type { Antenna } from '../../db';
|
2
|
+
export interface PolarAreaTraceData {
|
3
|
+
r: number[];
|
4
|
+
theta: number[];
|
5
|
+
type: 'scatterpolar';
|
6
|
+
mode: 'lines';
|
7
|
+
fill: 'toself';
|
8
|
+
name: string;
|
9
|
+
line: {
|
10
|
+
color: string;
|
11
|
+
width: number;
|
12
|
+
};
|
13
|
+
fillcolor: string;
|
14
|
+
opacity: number;
|
15
|
+
}
|
16
|
+
/**
|
17
|
+
* Convert antenna pattern to Plotly polar area trace data
|
18
|
+
*/
|
19
|
+
export declare function convertAntennaPatternToArea(pattern: number[], name: string, baseColor: string, opacity?: number, mechanicalTilt?: number, gainOffset?: number): PolarAreaTraceData;
|
20
|
+
/**
|
21
|
+
* Get area colors with appropriate transparency
|
22
|
+
*/
|
23
|
+
export declare function getAreaColors(electricalTilt: number, mechanicalTilt: number, baseColor: string): {
|
24
|
+
line: string;
|
25
|
+
fill: string;
|
26
|
+
};
|
27
|
+
/**
|
28
|
+
* Create polar area chart data for antenna patterns
|
29
|
+
*/
|
30
|
+
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[];
|
31
|
+
/**
|
32
|
+
* Create Plotly layout for polar area charts
|
33
|
+
*/
|
34
|
+
export declare function createPolarAreaLayout(title: string): {
|
35
|
+
title: {
|
36
|
+
text: string;
|
37
|
+
font: {
|
38
|
+
size: number;
|
39
|
+
color: string;
|
40
|
+
};
|
41
|
+
x: number;
|
42
|
+
xanchor: string;
|
43
|
+
};
|
44
|
+
polar: {
|
45
|
+
radialaxis: {
|
46
|
+
visible: boolean;
|
47
|
+
range: number[];
|
48
|
+
tickfont: {
|
49
|
+
size: number;
|
50
|
+
color: string;
|
51
|
+
};
|
52
|
+
gridcolor: string;
|
53
|
+
linecolor: string;
|
54
|
+
tickmode: string;
|
55
|
+
tick0: number;
|
56
|
+
dtick: number;
|
57
|
+
ticksuffix: string;
|
58
|
+
};
|
59
|
+
angularaxis: {
|
60
|
+
visible: boolean;
|
61
|
+
tickfont: {
|
62
|
+
size: number;
|
63
|
+
color: string;
|
64
|
+
};
|
65
|
+
gridcolor: string;
|
66
|
+
linecolor: string;
|
67
|
+
direction: string;
|
68
|
+
period: number;
|
69
|
+
rotation: number;
|
70
|
+
ticksuffix: string;
|
71
|
+
};
|
72
|
+
bgcolor: string;
|
73
|
+
};
|
74
|
+
margin: {
|
75
|
+
t: number;
|
76
|
+
r: number;
|
77
|
+
b: number;
|
78
|
+
l: number;
|
79
|
+
};
|
80
|
+
height: number;
|
81
|
+
paper_bgcolor: string;
|
82
|
+
plot_bgcolor: string;
|
83
|
+
legend: {
|
84
|
+
orientation: string;
|
85
|
+
x: number;
|
86
|
+
y: number;
|
87
|
+
xanchor: string;
|
88
|
+
};
|
89
|
+
};
|
@@ -0,0 +1,146 @@
|
|
1
|
+
/**
|
2
|
+
* Convert antenna pattern to Plotly polar area trace data
|
3
|
+
*/
|
4
|
+
export function convertAntennaPatternToArea(pattern, name, baseColor, opacity = 0.6, mechanicalTilt = 0, gainOffset = 0) {
|
5
|
+
// Convert attenuation to dB (negate values) and apply gain offset
|
6
|
+
let processedPattern = pattern.map(value => -value + gainOffset);
|
7
|
+
// Apply mechanical tilt by shifting the pattern
|
8
|
+
if (mechanicalTilt !== 0) {
|
9
|
+
const shiftedPattern = new Array(360).fill(0);
|
10
|
+
for (let i = 0; i < 360; i++) {
|
11
|
+
const sourceIndex = (i - mechanicalTilt + 360) % 360;
|
12
|
+
shiftedPattern[i] = processedPattern[sourceIndex] || 0;
|
13
|
+
}
|
14
|
+
processedPattern = shiftedPattern;
|
15
|
+
}
|
16
|
+
// Generate theta values (0-359 degrees) with proper rotation
|
17
|
+
const theta = [];
|
18
|
+
const r = [];
|
19
|
+
for (let i = 0; i < pattern.length; i++) {
|
20
|
+
let angle = i;
|
21
|
+
// Apply rotation to point antenna patterns to 0 degrees (North/up)
|
22
|
+
if (name.includes('Vertical')) {
|
23
|
+
angle = (i + 0) % 360; // Vertical patterns point to 0° (North/up)
|
24
|
+
}
|
25
|
+
else {
|
26
|
+
angle = (i + 270) % 360; // Rotate horizontal patterns 270° (or -90°) to point North
|
27
|
+
}
|
28
|
+
theta.push(angle);
|
29
|
+
r.push(processedPattern[i]);
|
30
|
+
}
|
31
|
+
// Close the area by adding the first point at the end
|
32
|
+
theta.push(theta[0]);
|
33
|
+
r.push(r[0]);
|
34
|
+
// Create semi-transparent fill color
|
35
|
+
const fillColor = baseColor.replace('rgb', 'rgba').replace(')', `, ${opacity})`);
|
36
|
+
return {
|
37
|
+
r,
|
38
|
+
theta,
|
39
|
+
type: 'scatterpolar',
|
40
|
+
mode: 'lines',
|
41
|
+
fill: 'toself',
|
42
|
+
name,
|
43
|
+
line: {
|
44
|
+
color: baseColor,
|
45
|
+
width: 2
|
46
|
+
},
|
47
|
+
fillcolor: fillColor,
|
48
|
+
opacity: 1 // Set to 1 since we control opacity via fillcolor
|
49
|
+
};
|
50
|
+
}
|
51
|
+
/**
|
52
|
+
* Get area colors with appropriate transparency
|
53
|
+
*/
|
54
|
+
export function getAreaColors(electricalTilt, mechanicalTilt, baseColor) {
|
55
|
+
return {
|
56
|
+
line: baseColor,
|
57
|
+
fill: baseColor.replace('rgb', 'rgba').replace(')', ', 0.3)')
|
58
|
+
};
|
59
|
+
}
|
60
|
+
/**
|
61
|
+
* Create polar area chart data for antenna patterns
|
62
|
+
*/
|
63
|
+
export function createPolarAreaChartData(selectedAntenna, selectedAntenna2, viewMode, showHorizontalPatterns, showVerticalPatterns, ant1ElectricalTilt, ant1MechanicalTilt, ant2ElectricalTilt, ant2MechanicalTilt, patternDisplayMode = 'normalized') {
|
64
|
+
const data = [];
|
65
|
+
// Calculate gain offsets for gain-adjusted display mode
|
66
|
+
let ant1GainOffset = 0;
|
67
|
+
let ant2GainOffset = 0;
|
68
|
+
if (patternDisplayMode === 'gain-adjusted' && viewMode === 'compare') {
|
69
|
+
const ant1Gain = selectedAntenna?.gain_dBd || 0;
|
70
|
+
const ant2Gain = selectedAntenna2?.gain_dBd || 0;
|
71
|
+
const maxGain = Math.max(ant1Gain, ant2Gain);
|
72
|
+
// Offset both antennas relative to the highest gain antenna
|
73
|
+
ant1GainOffset = ant1Gain - maxGain;
|
74
|
+
ant2GainOffset = ant2Gain - maxGain;
|
75
|
+
}
|
76
|
+
// Create antenna 1 pattern data based on visibility settings
|
77
|
+
if (selectedAntenna) {
|
78
|
+
if (showHorizontalPatterns) {
|
79
|
+
const horizontalData1 = convertAntennaPatternToArea(selectedAntenna.pattern || [], 'Antenna 1 - Horizontal', 'rgb(0, 102, 204)', 0.4, ant1MechanicalTilt, ant1GainOffset);
|
80
|
+
data.push(horizontalData1);
|
81
|
+
}
|
82
|
+
if (showVerticalPatterns) {
|
83
|
+
const verticalData1 = convertAntennaPatternToArea(selectedAntenna.vertical_pattern || [], 'Antenna 1 - Vertical', 'rgb(0, 61, 122)', 0.3, ant1MechanicalTilt, ant1GainOffset);
|
84
|
+
data.push(verticalData1);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
// Add second antenna if in compare mode and antenna 2 is selected
|
88
|
+
if (viewMode === 'compare' && selectedAntenna2) {
|
89
|
+
if (showHorizontalPatterns) {
|
90
|
+
const horizontalData2 = convertAntennaPatternToArea(selectedAntenna2.pattern || [], 'Antenna 2 - Horizontal', 'rgb(255, 215, 0)', 0.4, ant2MechanicalTilt, ant2GainOffset);
|
91
|
+
data.push(horizontalData2);
|
92
|
+
}
|
93
|
+
if (showVerticalPatterns) {
|
94
|
+
const verticalData2 = convertAntennaPatternToArea(selectedAntenna2.vertical_pattern || [], 'Antenna 2 - Vertical', 'rgb(230, 194, 0)', 0.3, ant2MechanicalTilt, ant2GainOffset);
|
95
|
+
data.push(verticalData2);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
return data;
|
99
|
+
}
|
100
|
+
/**
|
101
|
+
* Create Plotly layout for polar area charts
|
102
|
+
*/
|
103
|
+
export function createPolarAreaLayout(title) {
|
104
|
+
return {
|
105
|
+
title: {
|
106
|
+
text: title,
|
107
|
+
font: { size: 16, color: '#212529' },
|
108
|
+
x: 0.5,
|
109
|
+
xanchor: 'center'
|
110
|
+
},
|
111
|
+
polar: {
|
112
|
+
radialaxis: {
|
113
|
+
visible: true,
|
114
|
+
range: [-70, 0],
|
115
|
+
tickfont: { size: 10, color: '#6c757d' },
|
116
|
+
gridcolor: 'rgba(108, 117, 125, 0.3)',
|
117
|
+
linecolor: 'rgba(108, 117, 125, 0.5)',
|
118
|
+
tickmode: 'linear',
|
119
|
+
tick0: -70,
|
120
|
+
dtick: 10,
|
121
|
+
ticksuffix: ' dB'
|
122
|
+
},
|
123
|
+
angularaxis: {
|
124
|
+
visible: true,
|
125
|
+
tickfont: { size: 11, color: '#495057' },
|
126
|
+
gridcolor: 'rgba(108, 117, 125, 0.2)',
|
127
|
+
linecolor: 'rgba(108, 117, 125, 0.4)',
|
128
|
+
direction: 'clockwise',
|
129
|
+
period: 360,
|
130
|
+
rotation: 0,
|
131
|
+
ticksuffix: '°'
|
132
|
+
},
|
133
|
+
bgcolor: 'rgba(248, 249, 250, 0.5)'
|
134
|
+
},
|
135
|
+
margin: { t: 60, r: 40, b: 60, l: 40 },
|
136
|
+
height: 600,
|
137
|
+
paper_bgcolor: 'rgba(255, 255, 255, 0.95)',
|
138
|
+
plot_bgcolor: 'rgba(248, 249, 250, 0.3)',
|
139
|
+
legend: {
|
140
|
+
orientation: 'h',
|
141
|
+
x: 0.5,
|
142
|
+
y: -0.1,
|
143
|
+
xanchor: 'center'
|
144
|
+
}
|
145
|
+
};
|
146
|
+
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import type { Antenna } from '../../db';
|
2
|
+
export interface PolarBarTraceData {
|
3
|
+
r: number[];
|
4
|
+
theta: number[];
|
5
|
+
type: 'barpolar';
|
6
|
+
name: string;
|
7
|
+
marker: {
|
8
|
+
color: string;
|
9
|
+
opacity: number;
|
10
|
+
line: {
|
11
|
+
color: string;
|
12
|
+
width: number;
|
13
|
+
};
|
14
|
+
};
|
15
|
+
}
|
16
|
+
/**
|
17
|
+
* Convert antenna pattern to Plotly polar bar trace data
|
18
|
+
*/
|
19
|
+
export declare function convertAntennaPatternToBar(pattern: number[], name: string, color: string, opacity?: number, mechanicalTilt?: number): PolarBarTraceData;
|
20
|
+
/**
|
21
|
+
* Get bar color with appropriate opacity
|
22
|
+
*/
|
23
|
+
export declare function getBarColor(electricalTilt: number, mechanicalTilt: number, baseColor: string): string;
|
24
|
+
/**
|
25
|
+
* Create polar bar chart data for antenna patterns
|
26
|
+
*/
|
27
|
+
export declare function createPolarBarChartData(selectedAntenna: Antenna | null, selectedAntenna2: Antenna | null, viewMode: 'single' | 'compare', showHorizontalPatterns: boolean, showVerticalPatterns: boolean, ant1ElectricalTilt: number, ant1MechanicalTilt: number, ant2ElectricalTilt: number, ant2MechanicalTilt: number): PolarBarTraceData[];
|
28
|
+
/**
|
29
|
+
* Create Plotly layout for polar bar charts
|
30
|
+
*/
|
31
|
+
export declare function createPolarBarLayout(title: string): {
|
32
|
+
title: {
|
33
|
+
text: string;
|
34
|
+
font: {
|
35
|
+
size: number;
|
36
|
+
color: string;
|
37
|
+
};
|
38
|
+
x: number;
|
39
|
+
xanchor: string;
|
40
|
+
};
|
41
|
+
polar: {
|
42
|
+
radialaxis: {
|
43
|
+
visible: boolean;
|
44
|
+
range: number[];
|
45
|
+
tickfont: {
|
46
|
+
size: number;
|
47
|
+
color: string;
|
48
|
+
};
|
49
|
+
gridcolor: string;
|
50
|
+
linecolor: string;
|
51
|
+
tickmode: string;
|
52
|
+
tick0: number;
|
53
|
+
dtick: number;
|
54
|
+
ticksuffix: string;
|
55
|
+
};
|
56
|
+
angularaxis: {
|
57
|
+
visible: boolean;
|
58
|
+
tickfont: {
|
59
|
+
size: number;
|
60
|
+
color: string;
|
61
|
+
};
|
62
|
+
gridcolor: string;
|
63
|
+
linecolor: string;
|
64
|
+
direction: string;
|
65
|
+
period: number;
|
66
|
+
rotation: number;
|
67
|
+
ticksuffix: string;
|
68
|
+
};
|
69
|
+
bgcolor: string;
|
70
|
+
};
|
71
|
+
margin: {
|
72
|
+
t: number;
|
73
|
+
r: number;
|
74
|
+
b: number;
|
75
|
+
l: number;
|
76
|
+
};
|
77
|
+
height: number;
|
78
|
+
paper_bgcolor: string;
|
79
|
+
plot_bgcolor: string;
|
80
|
+
legend: {
|
81
|
+
orientation: string;
|
82
|
+
x: number;
|
83
|
+
y: number;
|
84
|
+
xanchor: string;
|
85
|
+
};
|
86
|
+
bargap: number;
|
87
|
+
barnorm: string;
|
88
|
+
};
|