@smartnet360/svelte-components 0.0.88 → 0.0.90
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/map-v3/features/cells/components/CellSettingsPanel.svelte +20 -4
- package/dist/map-v3/features/cells/constants.d.ts +8 -0
- package/dist/map-v3/features/cells/constants.js +163 -14
- package/dist/map-v3/features/cells/layers/CellsLayer.svelte +13 -6
- package/dist/map-v3/features/cells/logic/geometry.d.ts +1 -1
- package/dist/map-v3/features/cells/logic/geometry.js +4 -3
- package/dist/map-v3/features/cells/stores/cell.display.svelte.d.ts +4 -0
- package/dist/map-v3/features/cells/stores/cell.display.svelte.js +7 -0
- package/package.json +1 -1
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
id="cell-radius-slider"
|
|
22
22
|
type="range"
|
|
23
23
|
class="form-range w-100"
|
|
24
|
-
min="
|
|
25
|
-
max="
|
|
26
|
-
step="5"
|
|
24
|
+
min="5"
|
|
25
|
+
max="50"
|
|
26
|
+
step="2.5"
|
|
27
27
|
bind:value={displayStore.targetPixelSize}
|
|
28
28
|
/>
|
|
29
29
|
</div>
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
id="cell-line-width-slider"
|
|
41
41
|
type="range"
|
|
42
42
|
class="form-range w-100"
|
|
43
|
-
min="0
|
|
43
|
+
min="0"
|
|
44
44
|
max="5"
|
|
45
45
|
step="0.5"
|
|
46
46
|
bind:value={displayStore.lineWidth}
|
|
@@ -67,6 +67,22 @@
|
|
|
67
67
|
</div>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
70
|
+
<!-- Layer Grouping -->
|
|
71
|
+
<div class="row align-items-center g-2 mb-3">
|
|
72
|
+
<div class="col-4 text-secondary fw-semibold small text-uppercase">Layer Grouping</div>
|
|
73
|
+
<div class="col-8">
|
|
74
|
+
<select
|
|
75
|
+
class="form-select form-select-sm"
|
|
76
|
+
bind:value={displayStore.layerGrouping}
|
|
77
|
+
>
|
|
78
|
+
<option value="frequency">Classic (frequency-priority)</option>
|
|
79
|
+
<option value="technology">Technology Priority</option>
|
|
80
|
+
<option value="balanced">Balanced</option>
|
|
81
|
+
<option value="ltePriority">LTE Priority</option>
|
|
82
|
+
</select>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
70
86
|
<div class="border-top my-3"></div>
|
|
71
87
|
|
|
72
88
|
<!-- Show Labels -->
|
|
@@ -5,7 +5,15 @@
|
|
|
5
5
|
* Higher frequency bands typically rendered on top
|
|
6
6
|
*/
|
|
7
7
|
import type { TechnologyBandKey } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Layer Grouping Presets
|
|
10
|
+
* Controls visual layering strategy for overlapping sectors
|
|
11
|
+
*/
|
|
12
|
+
export type LayerGroupingPreset = 'frequency' | 'technology' | 'balanced';
|
|
13
|
+
export declare const Z_INDEX_PRESETS: Record<LayerGroupingPreset, Record<TechnologyBandKey, number>>;
|
|
14
|
+
export declare const BEAMWIDTH_BOOST_PRESETS: Record<LayerGroupingPreset, Record<TechnologyBandKey, number>>;
|
|
8
15
|
export declare const Z_INDEX_BY_BAND: Record<TechnologyBandKey, number>;
|
|
16
|
+
export declare const BEAMWIDTH_BOOST_BY_BAND: Record<TechnologyBandKey, number>;
|
|
9
17
|
/**
|
|
10
18
|
* Base Z-Index for Mapbox layer ordering
|
|
11
19
|
* Cells should render below sites but above base map features
|
|
@@ -4,21 +4,140 @@
|
|
|
4
4
|
* Controls which sectors appear on top when overlapping
|
|
5
5
|
* Higher frequency bands typically rendered on top
|
|
6
6
|
*/
|
|
7
|
+
export const Z_INDEX_PRESETS = {
|
|
8
|
+
'frequency': {
|
|
9
|
+
//low
|
|
10
|
+
'4G_700': 1,
|
|
11
|
+
'5G_700': 3,
|
|
12
|
+
'4G_800': 5,
|
|
13
|
+
'2G_900': 7,
|
|
14
|
+
'4G_900': 9,
|
|
15
|
+
//mid
|
|
16
|
+
'2G_1800': 11,
|
|
17
|
+
'4G_1800': 13,
|
|
18
|
+
'4G_2100': 15,
|
|
19
|
+
'5G_2100': 17,
|
|
20
|
+
'4G_2600': 19,
|
|
21
|
+
'5G_3500': 21,
|
|
22
|
+
},
|
|
23
|
+
'ltePriority': {
|
|
24
|
+
// Low band
|
|
25
|
+
'4G_700': 1,
|
|
26
|
+
'5G_700': 0.99,
|
|
27
|
+
'4G_800': 5,
|
|
28
|
+
'2G_900': 7,
|
|
29
|
+
'4G_900': 9,
|
|
30
|
+
// Mid band
|
|
31
|
+
'4G_1800': 15,
|
|
32
|
+
'2G_1800': 14.99,
|
|
33
|
+
'4G_2100': 19,
|
|
34
|
+
'5G_2100': 18.99,
|
|
35
|
+
'4G_2600': 23,
|
|
36
|
+
// High band
|
|
37
|
+
'5G_3500': 25,
|
|
38
|
+
},
|
|
39
|
+
'technology': {
|
|
40
|
+
// 5G on top
|
|
41
|
+
'5G_700': 30,
|
|
42
|
+
'5G_2100': 32,
|
|
43
|
+
'5G_3500': 34,
|
|
44
|
+
// 4G middle
|
|
45
|
+
'4G_700': 12,
|
|
46
|
+
'4G_800': 15,
|
|
47
|
+
'4G_900': 18,
|
|
48
|
+
'4G_1800': 19,
|
|
49
|
+
'4G_2100': 23,
|
|
50
|
+
'4G_2600': 26,
|
|
51
|
+
// 2G bottom
|
|
52
|
+
'2G_900': 5,
|
|
53
|
+
'2G_1800': 8,
|
|
54
|
+
},
|
|
55
|
+
'balanced': {
|
|
56
|
+
// Mix: newer tech gets boost within frequency range
|
|
57
|
+
'4G_700': 1,
|
|
58
|
+
'5G_700': 3,
|
|
59
|
+
'4G_800': 5,
|
|
60
|
+
'2G_900': 7,
|
|
61
|
+
'4G_900': 10,
|
|
62
|
+
// Mid band
|
|
63
|
+
'2G_1800': 14,
|
|
64
|
+
'4G_1800': 16,
|
|
65
|
+
'4G_2100': 19,
|
|
66
|
+
'5G_2100': 21,
|
|
67
|
+
'4G_2600': 23,
|
|
68
|
+
// High band
|
|
69
|
+
'5G_3500': 27,
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
export const BEAMWIDTH_BOOST_PRESETS = {
|
|
73
|
+
'frequency': {
|
|
74
|
+
'4G_700': 0,
|
|
75
|
+
'5G_700': 0,
|
|
76
|
+
'4G_800': 0,
|
|
77
|
+
'2G_900': 0,
|
|
78
|
+
'4G_900': 0,
|
|
79
|
+
'2G_1800': 0,
|
|
80
|
+
'4G_1800': 0,
|
|
81
|
+
'4G_2100': 0,
|
|
82
|
+
'5G_2100': 0,
|
|
83
|
+
'4G_2600': 0,
|
|
84
|
+
'5G_3500': 0
|
|
85
|
+
},
|
|
86
|
+
'ltePriority': {
|
|
87
|
+
// Boost 5G and 2G for visibility when frequency is priority
|
|
88
|
+
'4G_700': 0,
|
|
89
|
+
'5G_700': 15,
|
|
90
|
+
'4G_800': 0,
|
|
91
|
+
'2G_900': -15,
|
|
92
|
+
'4G_900': 0,
|
|
93
|
+
'2G_1800': 15,
|
|
94
|
+
'4G_1800': 0,
|
|
95
|
+
'4G_2100': 0,
|
|
96
|
+
'5G_2100': 15,
|
|
97
|
+
'4G_2600': 0,
|
|
98
|
+
'5G_3500': 15
|
|
99
|
+
},
|
|
100
|
+
'technology': {
|
|
101
|
+
// No boost needed - z-index separates clearly
|
|
102
|
+
'4G_700': 0,
|
|
103
|
+
'5G_700': 0,
|
|
104
|
+
'4G_800': 0,
|
|
105
|
+
'2G_900': 0,
|
|
106
|
+
'4G_900': 0,
|
|
107
|
+
'2G_1800': 0,
|
|
108
|
+
'4G_1800': 0,
|
|
109
|
+
'4G_2100': 0,
|
|
110
|
+
'5G_2100': 0,
|
|
111
|
+
'4G_2600': 0,
|
|
112
|
+
'5G_3500': 0
|
|
113
|
+
},
|
|
114
|
+
'balanced': {
|
|
115
|
+
// Moderate boost for 5G only
|
|
116
|
+
'4G_700': 0,
|
|
117
|
+
'5G_700': 0,
|
|
118
|
+
'4G_800': 0,
|
|
119
|
+
'2G_900': 0,
|
|
120
|
+
'4G_900': 0,
|
|
121
|
+
'2G_1800': 0,
|
|
122
|
+
'4G_1800': 0,
|
|
123
|
+
'4G_2100': 0,
|
|
124
|
+
'5G_2100': 0,
|
|
125
|
+
'4G_2600': 0,
|
|
126
|
+
'5G_3500': 0
|
|
127
|
+
}
|
|
128
|
+
};
|
|
7
129
|
export const Z_INDEX_BY_BAND = {
|
|
8
|
-
//
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
'4G_800':
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
//
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'4G_2600': 18,
|
|
20
|
-
//high
|
|
21
|
-
'5G_3500': 20,
|
|
130
|
+
// '2G_900': 1,
|
|
131
|
+
// '2G_1800': 3,
|
|
132
|
+
// '4G_700': 7,
|
|
133
|
+
// '4G_800': 9,
|
|
134
|
+
// '4G_900': 11,
|
|
135
|
+
// '4G_1800': 13,
|
|
136
|
+
// '4G_2100': 15,
|
|
137
|
+
// '4G_2600': 19,
|
|
138
|
+
// '5G_700': 23,
|
|
139
|
+
// '5G_2100': 25,
|
|
140
|
+
// '5G_3500': 27,
|
|
22
141
|
// //low
|
|
23
142
|
// '4G_700': 0,
|
|
24
143
|
// '5G_700': 2,
|
|
@@ -33,6 +152,36 @@ export const Z_INDEX_BY_BAND = {
|
|
|
33
152
|
// '4G_2600': 22,
|
|
34
153
|
// //high
|
|
35
154
|
// '5G_3500': 28,
|
|
155
|
+
//low
|
|
156
|
+
'4G_700': 1,
|
|
157
|
+
'5G_700': 0.99,
|
|
158
|
+
'4G_800': 5,
|
|
159
|
+
'2G_900': 7,
|
|
160
|
+
'4G_900': 9,
|
|
161
|
+
//mid
|
|
162
|
+
'4G_1800': 15,
|
|
163
|
+
'2G_1800': 14.99,
|
|
164
|
+
'4G_2100': 19,
|
|
165
|
+
'5G_2100': 18.99,
|
|
166
|
+
'4G_2600': 23,
|
|
167
|
+
//high
|
|
168
|
+
'5G_3500': 25,
|
|
169
|
+
};
|
|
170
|
+
export const BEAMWIDTH_BOOST_BY_BAND = {
|
|
171
|
+
// Low band
|
|
172
|
+
'4G_700': 0,
|
|
173
|
+
'5G_700': 15,
|
|
174
|
+
'4G_800': 0,
|
|
175
|
+
'2G_900': 0,
|
|
176
|
+
'4G_900': 0,
|
|
177
|
+
// Mid band
|
|
178
|
+
'2G_1800': 15,
|
|
179
|
+
'4G_1800': 0,
|
|
180
|
+
'4G_2100': 0,
|
|
181
|
+
'5G_2100': 15,
|
|
182
|
+
'4G_2600': 0,
|
|
183
|
+
// High band
|
|
184
|
+
'5G_3500': 15
|
|
36
185
|
};
|
|
37
186
|
/**
|
|
38
187
|
* Base Z-Index for Mapbox layer ordering
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import type { CellDisplayStore } from '../stores/cell.display.svelte';
|
|
7
7
|
import { groupCells, getColorForGroup } from '../logic/grouping';
|
|
8
8
|
import { generateCellArc, calculateRadiusInMeters } from '../logic/geometry';
|
|
9
|
-
import { Z_INDEX_BY_BAND } from '../constants';
|
|
10
9
|
import type { TechnologyBandKey } from '../types';
|
|
11
10
|
import type mapboxgl from 'mapbox-gl';
|
|
12
11
|
|
|
@@ -86,6 +85,9 @@
|
|
|
86
85
|
['get', 'dashArray'],
|
|
87
86
|
['literal', []]
|
|
88
87
|
]
|
|
88
|
+
},
|
|
89
|
+
layout: {
|
|
90
|
+
'line-sort-key': ['get', 'zIndex']
|
|
89
91
|
}
|
|
90
92
|
});
|
|
91
93
|
}
|
|
@@ -124,6 +126,7 @@
|
|
|
124
126
|
const _registryVersion = registry.version;
|
|
125
127
|
const _l1 = displayStore.level1;
|
|
126
128
|
const _l2 = displayStore.level2;
|
|
129
|
+
const _layerGrouping = displayStore.layerGrouping;
|
|
127
130
|
|
|
128
131
|
updateLayer();
|
|
129
132
|
});
|
|
@@ -171,19 +174,23 @@
|
|
|
171
174
|
// 4. BBox Filter (Simple point check)
|
|
172
175
|
if (bounds.contains([cell.longitude, cell.latitude])) {
|
|
173
176
|
// 5. Z-Index Lookup
|
|
174
|
-
const zIndexKey = `${cell.tech}_${cell.frq}` as TechnologyBandKey;
|
|
175
|
-
const zIndex =
|
|
177
|
+
const zIndexKey = `${cell.tech}_${cell.frq}` as TechnologyBandKey;
|
|
178
|
+
const zIndex = displayStore.currentZIndex[zIndexKey] ?? 10;
|
|
176
179
|
|
|
177
180
|
// 6. Calculate Scaled Radius based on Z-Index
|
|
178
181
|
// Higher Z-index (Top layer) = Smaller radius
|
|
179
182
|
// Lower Z-index (Bottom layer) = Larger radius
|
|
180
183
|
// This ensures stacked cells are visible
|
|
181
|
-
const MAX_Z =
|
|
184
|
+
const MAX_Z = 35;
|
|
182
185
|
const scaleFactor = 1 + Math.max(0, MAX_Z - zIndex) * 0.08; // 8% size diff per layer
|
|
183
186
|
const effectiveRadius = radiusMeters * scaleFactor;
|
|
184
187
|
|
|
185
|
-
// 7.
|
|
186
|
-
const
|
|
188
|
+
// 7. Apply beamwidth boost from displayStore preset
|
|
189
|
+
const beamwidthBoost = displayStore.currentBeamwidthBoost[zIndexKey] || 0;
|
|
190
|
+
const adjustedBeamwidth = cell.beamwidth + beamwidthBoost;
|
|
191
|
+
|
|
192
|
+
// 8. Generate Arc
|
|
193
|
+
const feature = generateCellArc(cell, effectiveRadius, zIndex, style.color, adjustedBeamwidth);
|
|
187
194
|
features.push(feature);
|
|
188
195
|
}
|
|
189
196
|
}
|
|
@@ -9,4 +9,4 @@ export declare function calculateRadiusInMeters(latitude: number, zoom: number,
|
|
|
9
9
|
/**
|
|
10
10
|
* Generates a sector arc GeoJSON feature for a cell
|
|
11
11
|
*/
|
|
12
|
-
export declare function generateCellArc(cell: Cell, radiusMeters: number, zIndex: number, color: string): GeoJSON.Feature<GeoJSON.Polygon>;
|
|
12
|
+
export declare function generateCellArc(cell: Cell, radiusMeters: number, zIndex: number, color: string, beamwidthOverride?: number): GeoJSON.Feature<GeoJSON.Polygon>;
|
|
@@ -13,10 +13,11 @@ export function calculateRadiusInMeters(latitude, zoom, targetPixelSize) {
|
|
|
13
13
|
/**
|
|
14
14
|
* Generates a sector arc GeoJSON feature for a cell
|
|
15
15
|
*/
|
|
16
|
-
export function generateCellArc(cell, radiusMeters, zIndex, color) {
|
|
16
|
+
export function generateCellArc(cell, radiusMeters, zIndex, color, beamwidthOverride) {
|
|
17
17
|
const center = [cell.longitude, cell.latitude];
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
const beamwidth = beamwidthOverride ?? cell.beamwidth;
|
|
19
|
+
const bearing1 = cell.azimuth - (beamwidth / 2);
|
|
20
|
+
const bearing2 = cell.azimuth + (beamwidth / 2);
|
|
20
21
|
// Use Turf to generate the sector
|
|
21
22
|
// Note: turf.sector takes (center, radius, bearing1, bearing2)
|
|
22
23
|
// Radius must be in kilometers for default turf units, or specify units
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { CellGroupingField } from '../types';
|
|
2
|
+
import type { LayerGroupingPreset } from '../constants';
|
|
2
3
|
export declare class CellDisplayStore {
|
|
3
4
|
key: string;
|
|
4
5
|
targetPixelSize: number;
|
|
5
6
|
fillOpacity: number;
|
|
6
7
|
lineWidth: number;
|
|
7
8
|
showLabels: boolean;
|
|
9
|
+
layerGrouping: LayerGroupingPreset;
|
|
8
10
|
level1: CellGroupingField;
|
|
9
11
|
level2: CellGroupingField;
|
|
12
|
+
currentZIndex: Record<string, number>;
|
|
13
|
+
currentBeamwidthBoost: Record<string, number>;
|
|
10
14
|
labelPixelDistance: number;
|
|
11
15
|
labelFontSize: number;
|
|
12
16
|
labelAzimuthTolerance: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { browser } from '$app/environment';
|
|
2
|
+
import { Z_INDEX_PRESETS, BEAMWIDTH_BOOST_PRESETS } from '../constants';
|
|
2
3
|
export class CellDisplayStore {
|
|
3
4
|
key = 'map-v3-cell-display';
|
|
4
5
|
// State
|
|
@@ -6,9 +7,13 @@ export class CellDisplayStore {
|
|
|
6
7
|
fillOpacity = $state(0.6);
|
|
7
8
|
lineWidth = $state(1);
|
|
8
9
|
showLabels = $state(false);
|
|
10
|
+
layerGrouping = $state('frequency');
|
|
9
11
|
// Grouping
|
|
10
12
|
level1 = $state('tech');
|
|
11
13
|
level2 = $state('fband');
|
|
14
|
+
// Derived preset configurations
|
|
15
|
+
currentZIndex = $derived.by(() => Z_INDEX_PRESETS[this.layerGrouping]);
|
|
16
|
+
currentBeamwidthBoost = $derived.by(() => BEAMWIDTH_BOOST_PRESETS[this.layerGrouping]);
|
|
12
17
|
// Label Settings
|
|
13
18
|
labelPixelDistance = $state(60);
|
|
14
19
|
labelFontSize = $state(12);
|
|
@@ -29,6 +34,7 @@ export class CellDisplayStore {
|
|
|
29
34
|
this.fillOpacity = parsed.fillOpacity ?? 0.6;
|
|
30
35
|
this.lineWidth = parsed.lineWidth ?? 1;
|
|
31
36
|
this.showLabels = parsed.showLabels ?? false;
|
|
37
|
+
this.layerGrouping = parsed.layerGrouping ?? 'frequency';
|
|
32
38
|
this.level1 = parsed.level1 ?? 'tech';
|
|
33
39
|
this.level2 = parsed.level2 ?? 'fband';
|
|
34
40
|
this.labelPixelDistance = parsed.labelPixelDistance ?? 60;
|
|
@@ -50,6 +56,7 @@ export class CellDisplayStore {
|
|
|
50
56
|
fillOpacity: this.fillOpacity,
|
|
51
57
|
lineWidth: this.lineWidth,
|
|
52
58
|
showLabels: this.showLabels,
|
|
59
|
+
layerGrouping: this.layerGrouping,
|
|
53
60
|
level1: this.level1,
|
|
54
61
|
level2: this.level2,
|
|
55
62
|
labelPixelDistance: this.labelPixelDistance,
|