mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
Merge remote-tracking branch 'origin/calculate-refrac-los' into combined-prs
This commit is contained in:
commit
de63733bb9
35 changed files with 1259 additions and 57 deletions
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Име на точката",
|
||||
"losShowPanelTooltip": "Показване на LOS панел",
|
||||
"losHidePanelTooltip": "Скриване на LOS панела",
|
||||
"losElevationAttribution": "Данни за надморска височина: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Данни за надморска височина: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Радиохоризонт",
|
||||
"losLegendLosBeam": "Линия на видимост",
|
||||
"losLegendTerrain": "Терен",
|
||||
"losFrequencyLabel": "Честота",
|
||||
"losFrequencyInfoTooltip": "Преглед на детайли за изчислението",
|
||||
"losFrequencyDialogTitle": "Изчисляване на радиохоризонта",
|
||||
"losFrequencyDialogDescription": "Започвайки от k={baselineK} при {baselineFreq} MHz, изчислението коригира k-фактора за текущата {frequencyMHz} MHz лента, която определя границата на извития радиохоризонт.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1746,5 +1746,29 @@
|
|||
"losPointName": "Punktname",
|
||||
"losShowPanelTooltip": "LOS-Panel anzeigen",
|
||||
"losHidePanelTooltip": "LOS-Panel ausblenden",
|
||||
"losElevationAttribution": "Höhendaten: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Höhendaten: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Funkhorizont",
|
||||
"losLegendLosBeam": "Sichtlinie",
|
||||
"losLegendTerrain": "Gelände",
|
||||
"losFrequencyLabel": "Frequenz",
|
||||
"losFrequencyInfoTooltip": "Details zur Berechnung anzeigen",
|
||||
"losFrequencyDialogTitle": "Berechnung des Funkhorizonts",
|
||||
"losFrequencyDialogDescription": "Ausgehend von k={baselineK} bei {baselineFreq} MHz passt die Berechnung den k-Faktor für das aktuelle {frequencyMHz} MHz-Band an, das die gekrümmte Funkhorizontobergrenze definiert.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1667,6 +1667,30 @@
|
|||
"losShowPanelTooltip": "Show LOS panel",
|
||||
"losHidePanelTooltip": "Hide LOS panel",
|
||||
"losElevationAttribution": "Elevation data: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Radio horizon",
|
||||
"losLegendLosBeam": "LOS beam",
|
||||
"losLegendTerrain": "Terrain",
|
||||
"losFrequencyLabel": "Frequency",
|
||||
"losFrequencyInfoTooltip": "View calculation details",
|
||||
"losFrequencyDialogTitle": "Radio horizon calculation",
|
||||
"losFrequencyDialogDescription": "Starting from k={baselineK} at {baselineFreq} MHz, the calculation adjusts the k-factor for the current {frequencyMHz} MHz band, which defines the curved radio horizon cap.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contacts_pathTrace": "Path Trace",
|
||||
"contacts_ping": "Ping",
|
||||
"contacts_repeaterPathTrace": "Path trace to repeater",
|
||||
|
|
@ -1747,4 +1771,4 @@
|
|||
"settings_gpxExportShareSubject": "meshcore-open GPX map data export",
|
||||
"snrIndicator_nearByRepeaters": "Nearby Repeaters",
|
||||
"snrIndicator_lastSeen": "Last seen"
|
||||
}
|
||||
}
|
||||
|
|
@ -1746,5 +1746,29 @@
|
|||
"losPointName": "Nombre del punto",
|
||||
"losShowPanelTooltip": "Mostrar panel LOS",
|
||||
"losHidePanelTooltip": "Ocultar panel LOS",
|
||||
"losElevationAttribution": "Datos de elevación: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Datos de elevación: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Horizonte radioeléctrico",
|
||||
"losLegendLosBeam": "Línea de visión",
|
||||
"losLegendTerrain": "Terreno",
|
||||
"losFrequencyLabel": "Frecuencia",
|
||||
"losFrequencyInfoTooltip": "Ver detalles del cálculo",
|
||||
"losFrequencyDialogTitle": "Cálculo del horizonte radioeléctrico",
|
||||
"losFrequencyDialogDescription": "A partir de k={baselineK} en {baselineFreq} MHz, el cálculo ajusta el factor k para la banda actual de {frequencyMHz} MHz, que define el límite curvo del horizonte de radio.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Nom du point",
|
||||
"losShowPanelTooltip": "Afficher le panneau LOS",
|
||||
"losHidePanelTooltip": "Masquer le panneau LOS",
|
||||
"losElevationAttribution": "Données d'altitude : Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Données d’altitude : Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Horizon radio",
|
||||
"losLegendLosBeam": "Ligne de visée",
|
||||
"losLegendTerrain": "Terrain",
|
||||
"losFrequencyLabel": "Fréquence",
|
||||
"losFrequencyInfoTooltip": "Voir les détails du calcul",
|
||||
"losFrequencyDialogTitle": "Calcul de l’horizon radio",
|
||||
"losFrequencyDialogDescription": "À partir de k={baselineK} à {baselineFreq} MHz, le calcul ajuste le facteur k pour la bande actuelle de {frequencyMHz} MHz, ce qui définit la limite incurvée de l'horizon radio.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Nome del punto",
|
||||
"losShowPanelTooltip": "Mostra il pannello LOS",
|
||||
"losHidePanelTooltip": "Nascondi il pannello LOS",
|
||||
"losElevationAttribution": "Dati di elevazione: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Dati di elevazione: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Orizzonte radio",
|
||||
"losLegendLosBeam": "Linea di vista",
|
||||
"losLegendTerrain": "Terreno",
|
||||
"losFrequencyLabel": "Frequenza",
|
||||
"losFrequencyInfoTooltip": "Visualizza i dettagli del calcolo",
|
||||
"losFrequencyDialogTitle": "Calcolo dell’orizzonte radio",
|
||||
"losFrequencyDialogDescription": "Partendo da k={baselineK} a {baselineFreq} MHz, il calcolo regola il fattore k per l'attuale banda {frequencyMHz} MHz, che definisce il limite curvo dell'orizzonte radio.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5004,6 +5004,53 @@ abstract class AppLocalizations {
|
|||
/// **'Elevation data: Open-Meteo (CC BY 4.0)'**
|
||||
String get losElevationAttribution;
|
||||
|
||||
/// No description provided for @losLegendRadioHorizon.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Radio horizon'**
|
||||
String get losLegendRadioHorizon;
|
||||
|
||||
/// No description provided for @losLegendLosBeam.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'LOS beam'**
|
||||
String get losLegendLosBeam;
|
||||
|
||||
/// No description provided for @losLegendTerrain.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Terrain'**
|
||||
String get losLegendTerrain;
|
||||
|
||||
/// No description provided for @losFrequencyLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Frequency'**
|
||||
String get losFrequencyLabel;
|
||||
|
||||
/// No description provided for @losFrequencyInfoTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'View calculation details'**
|
||||
String get losFrequencyInfoTooltip;
|
||||
|
||||
/// No description provided for @losFrequencyDialogTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Radio horizon calculation'**
|
||||
String get losFrequencyDialogTitle;
|
||||
|
||||
/// Explain how the calculation uses the baseline frequency and derived k-factor.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Starting from k={baselineK} at {baselineFreq} MHz, the calculation adjusts the k-factor for the current {frequencyMHz} MHz band, which defines the curved radio horizon cap.'**
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
);
|
||||
|
||||
/// No description provided for @contacts_pathTrace.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
|
|||
|
|
@ -2867,6 +2867,34 @@ class AppLocalizationsBg extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Данни за надморска височина: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Радиохоризонт';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Линия на видимост';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Терен';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Честота';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Преглед на детайли за изчислението';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Изчисляване на радиохоризонта';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Започвайки от k=$baselineK при $baselineFreq MHz, изчислението коригира k-фактора за текущата $frequencyMHz MHz лента, която определя границата на извития радиохоризонт.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Пътен проследяване';
|
||||
|
||||
|
|
|
|||
|
|
@ -2873,6 +2873,34 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get losElevationAttribution => 'Höhendaten: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Funkhorizont';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Sichtlinie';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Gelände';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frequenz';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Details zur Berechnung anzeigen';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Berechnung des Funkhorizonts';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Ausgehend von k=$baselineK bei $baselineFreq MHz passt die Berechnung den k-Faktor für das aktuelle $frequencyMHz MHz-Band an, das die gekrümmte Funkhorizontobergrenze definiert.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Pfadverfolgung';
|
||||
|
||||
|
|
|
|||
|
|
@ -2824,6 +2824,34 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Elevation data: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Radio horizon';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'LOS beam';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terrain';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frequency';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'View calculation details';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Radio horizon calculation';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Starting from k=$baselineK at $baselineFreq MHz, the calculation adjusts the k-factor for the current $frequencyMHz MHz band, which defines the curved radio horizon cap.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Path Trace';
|
||||
|
||||
|
|
|
|||
|
|
@ -2867,6 +2867,34 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Datos de elevación: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Horizonte radioeléctrico';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Línea de visión';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terreno';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frecuencia';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Ver detalles del cálculo';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Cálculo del horizonte radioeléctrico';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'A partir de k=$baselineK en $baselineFreq MHz, el cálculo ajusta el factor k para la banda actual de $frequencyMHz MHz, que define el límite curvo del horizonte de radio.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Rastreo de caminos';
|
||||
|
||||
|
|
|
|||
|
|
@ -2880,7 +2880,35 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get losElevationAttribution =>
|
||||
'Données d\'altitude : Open-Meteo (CC BY 4.0)';
|
||||
'Données d’altitude : Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Horizon radio';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Ligne de visée';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terrain';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Fréquence';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Voir les détails du calcul';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Calcul de l’horizon radio';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'À partir de k=$baselineK à $baselineFreq MHz, le calcul ajuste le facteur k pour la bande actuelle de $frequencyMHz MHz, ce qui définit la limite incurvée de l\'horizon radio.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Traçage de chemin';
|
||||
|
|
|
|||
|
|
@ -2867,6 +2867,34 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Dati di elevazione: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Orizzonte radio';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Linea di vista';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terreno';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frequenza';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Visualizza i dettagli del calcolo';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Calcolo dell’orizzonte radio';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Partendo da k=$baselineK a $baselineFreq MHz, il calcolo regola il fattore k per l\'attuale banda $frequencyMHz MHz, che definisce il limite curvo dell\'orizzonte radio.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Traccia Percorso';
|
||||
|
||||
|
|
|
|||
|
|
@ -2857,6 +2857,34 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Hoogtegegevens: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Radiohorizon';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Zichtlijn';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terrein';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frequentie';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Bekijk details van de berekening';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Berekening van de radiohorizon';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Beginnend met k=$baselineK bij $baselineFreq MHz, wordt bij de berekening de k-factor aangepast voor de huidige $frequencyMHz MHz-band, die de gebogen radiohorizonkap definieert.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Pad Traceren';
|
||||
|
||||
|
|
|
|||
|
|
@ -2863,6 +2863,34 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Dane dotyczące wysokości: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Horyzont radiowy';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Linia widoczności';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Teren';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Częstotliwość';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Zobacz szczegóły obliczenia';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Obliczanie horyzontu radiowego';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Zaczynając od k=$baselineK przy $baselineFreq MHz, obliczenia korygują współczynnik k dla bieżącego pasma $frequencyMHz MHz, które definiuje zakrzywiony limit horyzontu radiowego.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Śledzenie Ścieżek';
|
||||
|
||||
|
|
|
|||
|
|
@ -2866,6 +2866,34 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Dados de elevação: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Horizonte de rádio';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Linha de visada';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terreno';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frequência';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Ver detalhes do cálculo';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Cálculo do horizonte de rádio';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Começando em k=$baselineK em $baselineFreq MHz, o cálculo ajusta o fator k para a banda atual de $frequencyMHz MHz, que define o limite do horizonte de rádio curvo.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Traçado de Caminho';
|
||||
|
||||
|
|
|
|||
|
|
@ -2869,6 +2869,34 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Данные о высоте: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Радиогоризонт';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Линия прямой видимости';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Рельеф';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Частота';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Просмотреть детали расчёта';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Расчёт радиогоризонта';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Начиная с k=$baselineK на частоте $baselineFreq МГц, расчет корректирует коэффициент k для текущего диапазона $frequencyMHz МГц, который определяет изогнутую границу радиогоризонта.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Трассировка пути';
|
||||
|
||||
|
|
|
|||
|
|
@ -2851,6 +2851,34 @@ class AppLocalizationsSk extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Údaje o nadmorskej výške: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Rádiový horizont';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Priama viditeľnosť';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terén';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frekvencia';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Zobraziť podrobnosti výpočtu';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Výpočet rádiového horizontu';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Počnúc od k=$baselineK pri $baselineFreq MHz výpočet upraví k-faktor pre aktuálne pásmo $frequencyMHz MHz, ktorý definuje zakrivený strop rádiového horizontu.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Sledovanie lúčov';
|
||||
|
||||
|
|
|
|||
|
|
@ -2854,6 +2854,34 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Podatki o višini: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Radijski horizont';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Linija vidnosti';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Teren';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frekvenca';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Prikaži podrobnosti izračuna';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Izračun radijskega horizonta';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Začenši od k=$baselineK pri $baselineFreq MHz, izračun prilagodi k-faktor za trenutni pas $frequencyMHz MHz, ki določa ukrivljeno zgornjo mejo radijskega horizonta.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Sledenje poti';
|
||||
|
||||
|
|
|
|||
|
|
@ -2837,6 +2837,34 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||
@override
|
||||
String get losElevationAttribution => 'Höjddata: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Radiohorisont';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Siktlinje';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Terräng';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Frekvens';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Visa detaljer om beräkningen';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Beräkning av radiohorisonten';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Med start från k=$baselineK vid $baselineFreq MHz, justerar beräkningen k-faktorn för det aktuella $frequencyMHz MHz-bandet, som definierar den böjda radiohorisonten.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Path Trace';
|
||||
|
||||
|
|
|
|||
|
|
@ -2877,6 +2877,34 @@ class AppLocalizationsUk extends AppLocalizations {
|
|||
String get losElevationAttribution =>
|
||||
'Дані про висоту: Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => 'Радіогоризонт';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => 'Лінія прямої видимості';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => 'Рельєф';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => 'Частота';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => 'Переглянути деталі розрахунку';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => 'Розрахунок радіогоризонту';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return 'Починаючи з k=$baselineK на $baselineFreq МГц, обчислення коригує k-фактор для поточного діапазону $frequencyMHz МГц, який визначає викривлену межу радіогоризонту.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => 'Трасування шляхів';
|
||||
|
||||
|
|
|
|||
|
|
@ -2715,6 +2715,34 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||
@override
|
||||
String get losElevationAttribution => '高程数据:Open-Meteo (CC BY 4.0)';
|
||||
|
||||
@override
|
||||
String get losLegendRadioHorizon => '无线电地平线';
|
||||
|
||||
@override
|
||||
String get losLegendLosBeam => '视距波束';
|
||||
|
||||
@override
|
||||
String get losLegendTerrain => '地形';
|
||||
|
||||
@override
|
||||
String get losFrequencyLabel => '频率';
|
||||
|
||||
@override
|
||||
String get losFrequencyInfoTooltip => '查看计算详情';
|
||||
|
||||
@override
|
||||
String get losFrequencyDialogTitle => '无线电地平线计算';
|
||||
|
||||
@override
|
||||
String losFrequencyDialogDescription(
|
||||
double baselineK,
|
||||
double baselineFreq,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
return '从 $baselineFreq MHz 处的 k=$baselineK 开始,计算调整当前 $frequencyMHz MHz 频段的 k 因子,该因子定义了弯曲的无线电范围上限。';
|
||||
}
|
||||
|
||||
@override
|
||||
String get contacts_pathTrace => '路径追踪';
|
||||
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Puntnaam",
|
||||
"losShowPanelTooltip": "Toon LOS-paneel",
|
||||
"losHidePanelTooltip": "LOS-paneel verbergen",
|
||||
"losElevationAttribution": "Hoogtegegevens: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Hoogtegegevens: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Radiohorizon",
|
||||
"losLegendLosBeam": "Zichtlijn",
|
||||
"losLegendTerrain": "Terrein",
|
||||
"losFrequencyLabel": "Frequentie",
|
||||
"losFrequencyInfoTooltip": "Bekijk details van de berekening",
|
||||
"losFrequencyDialogTitle": "Berekening van de radiohorizon",
|
||||
"losFrequencyDialogDescription": "Beginnend met k={baselineK} bij {baselineFreq} MHz, wordt bij de berekening de k-factor aangepast voor de huidige {frequencyMHz} MHz-band, die de gebogen radiohorizonkap definieert.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Nazwa punktu",
|
||||
"losShowPanelTooltip": "Pokaż panel LOS",
|
||||
"losHidePanelTooltip": "Ukryj panel LOS",
|
||||
"losElevationAttribution": "Dane dotyczące wysokości: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Dane dotyczące wysokości: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Horyzont radiowy",
|
||||
"losLegendLosBeam": "Linia widoczności",
|
||||
"losLegendTerrain": "Teren",
|
||||
"losFrequencyLabel": "Częstotliwość",
|
||||
"losFrequencyInfoTooltip": "Zobacz szczegóły obliczenia",
|
||||
"losFrequencyDialogTitle": "Obliczanie horyzontu radiowego",
|
||||
"losFrequencyDialogDescription": "Zaczynając od k={baselineK} przy {baselineFreq} MHz, obliczenia korygują współczynnik k dla bieżącego pasma {frequencyMHz} MHz, które definiuje zakrzywiony limit horyzontu radiowego.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Nome do ponto",
|
||||
"losShowPanelTooltip": "Mostrar painel LOS",
|
||||
"losHidePanelTooltip": "Ocultar painel LOS",
|
||||
"losElevationAttribution": "Dados de elevação: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Dados de elevação: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Horizonte de rádio",
|
||||
"losLegendLosBeam": "Linha de visada",
|
||||
"losLegendTerrain": "Terreno",
|
||||
"losFrequencyLabel": "Frequência",
|
||||
"losFrequencyInfoTooltip": "Ver detalhes do cálculo",
|
||||
"losFrequencyDialogTitle": "Cálculo do horizonte de rádio",
|
||||
"losFrequencyDialogDescription": "Começando em k={baselineK} em {baselineFreq} MHz, o cálculo ajusta o fator k para a banda atual de {frequencyMHz} MHz, que define o limite do horizonte de rádio curvo.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -958,5 +958,29 @@
|
|||
"losPointName": "Имя точки",
|
||||
"losShowPanelTooltip": "Показать панель LOS",
|
||||
"losHidePanelTooltip": "Скрыть панель LOS",
|
||||
"losElevationAttribution": "Данные о высоте: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Данные о высоте: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Радиогоризонт",
|
||||
"losLegendLosBeam": "Линия прямой видимости",
|
||||
"losLegendTerrain": "Рельеф",
|
||||
"losFrequencyLabel": "Частота",
|
||||
"losFrequencyInfoTooltip": "Просмотреть детали расчёта",
|
||||
"losFrequencyDialogTitle": "Расчёт радиогоризонта",
|
||||
"losFrequencyDialogDescription": "Начиная с k={baselineK} на частоте {baselineFreq} МГц, расчет корректирует коэффициент k для текущего диапазона {frequencyMHz} МГц, который определяет изогнутую границу радиогоризонта.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Názov bodu",
|
||||
"losShowPanelTooltip": "Zobraziť panel LOS",
|
||||
"losHidePanelTooltip": "Skryť panel LOS",
|
||||
"losElevationAttribution": "Údaje o nadmorskej výške: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Údaje o nadmorskej výške: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Rádiový horizont",
|
||||
"losLegendLosBeam": "Priama viditeľnosť",
|
||||
"losLegendTerrain": "Terén",
|
||||
"losFrequencyLabel": "Frekvencia",
|
||||
"losFrequencyInfoTooltip": "Zobraziť podrobnosti výpočtu",
|
||||
"losFrequencyDialogTitle": "Výpočet rádiového horizontu",
|
||||
"losFrequencyDialogDescription": "Počnúc od k={baselineK} pri {baselineFreq} MHz výpočet upraví k-faktor pre aktuálne pásmo {frequencyMHz} MHz, ktorý definuje zakrivený strop rádiového horizontu.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Ime točke",
|
||||
"losShowPanelTooltip": "Pokaži ploščo LOS",
|
||||
"losHidePanelTooltip": "Skrij ploščo LOS",
|
||||
"losElevationAttribution": "Podatki o višini: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Podatki o višini: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Radijski horizont",
|
||||
"losLegendLosBeam": "Linija vidnosti",
|
||||
"losLegendTerrain": "Teren",
|
||||
"losFrequencyLabel": "Frekvenca",
|
||||
"losFrequencyInfoTooltip": "Prikaži podrobnosti izračuna",
|
||||
"losFrequencyDialogTitle": "Izračun radijskega horizonta",
|
||||
"losFrequencyDialogDescription": "Začenši od k={baselineK} pri {baselineFreq} MHz, izračun prilagodi k-faktor za trenutni pas {frequencyMHz} MHz, ki določa ukrivljeno zgornjo mejo radijskega horizonta.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Punktnamn",
|
||||
"losShowPanelTooltip": "Visa LOS-panelen",
|
||||
"losHidePanelTooltip": "Dölj LOS-panelen",
|
||||
"losElevationAttribution": "Höjddata: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Höjddata: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Radiohorisont",
|
||||
"losLegendLosBeam": "Siktlinje",
|
||||
"losLegendTerrain": "Terräng",
|
||||
"losFrequencyLabel": "Frekvens",
|
||||
"losFrequencyInfoTooltip": "Visa detaljer om beräkningen",
|
||||
"losFrequencyDialogTitle": "Beräkning av radiohorisonten",
|
||||
"losFrequencyDialogDescription": "Med start från k={baselineK} vid {baselineFreq} MHz, justerar beräkningen k-faktorn för det aktuella {frequencyMHz} MHz-bandet, som definierar den böjda radiohorisonten.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "Назва точки",
|
||||
"losShowPanelTooltip": "Показати панель LOS",
|
||||
"losHidePanelTooltip": "Приховати панель LOS",
|
||||
"losElevationAttribution": "Дані про висоту: Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "Дані про висоту: Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "Радіогоризонт",
|
||||
"losLegendLosBeam": "Лінія прямої видимості",
|
||||
"losLegendTerrain": "Рельєф",
|
||||
"losFrequencyLabel": "Частота",
|
||||
"losFrequencyInfoTooltip": "Переглянути деталі розрахунку",
|
||||
"losFrequencyDialogTitle": "Розрахунок радіогоризонту",
|
||||
"losFrequencyDialogDescription": "Починаючи з k={baselineK} на {baselineFreq} МГц, обчислення коригує k-фактор для поточного діапазону {frequencyMHz} МГц, який визначає викривлену межу радіогоризонту.",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1718,5 +1718,29 @@
|
|||
"losPointName": "点名称",
|
||||
"losShowPanelTooltip": "显示 LOS 面板",
|
||||
"losHidePanelTooltip": "隐藏 LOS 面板",
|
||||
"losElevationAttribution": "高程数据:Open-Meteo (CC BY 4.0)"
|
||||
}
|
||||
"losElevationAttribution": "高程数据:Open-Meteo (CC BY 4.0)",
|
||||
"losLegendRadioHorizon": "无线电地平线",
|
||||
"losLegendLosBeam": "视距波束",
|
||||
"losLegendTerrain": "地形",
|
||||
"losFrequencyLabel": "频率",
|
||||
"losFrequencyInfoTooltip": "查看计算详情",
|
||||
"losFrequencyDialogTitle": "无线电地平线计算",
|
||||
"losFrequencyDialogDescription": "从 {baselineFreq} MHz 处的 k={baselineK} 开始,计算调整当前 {frequencyMHz} MHz 频段的 k 因子,该因子定义了弯曲的无线电范围上限。",
|
||||
"@losFrequencyDialogDescription": {
|
||||
"description": "Explain how the calculation uses the baseline frequency and derived k-factor.",
|
||||
"placeholders": {
|
||||
"baselineK": {
|
||||
"type": "double"
|
||||
},
|
||||
"baselineFreq": {
|
||||
"type": "double"
|
||||
},
|
||||
"frequencyMHz": {
|
||||
"type": "double"
|
||||
},
|
||||
"kFactor": {
|
||||
"type": "double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import '../services/app_settings_service.dart';
|
|||
import '../services/line_of_sight_service.dart';
|
||||
import '../services/map_tile_cache_service.dart';
|
||||
import '../utils/route_transitions.dart';
|
||||
import '../connector/meshcore_connector.dart';
|
||||
import '../widgets/app_bar.dart';
|
||||
import '../widgets/quick_switch_bar.dart';
|
||||
|
||||
|
|
@ -110,10 +111,13 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
|
|||
});
|
||||
|
||||
try {
|
||||
final connector = context.watch<MeshCoreConnector>();
|
||||
final frequencyMHz = _normalizeFrequencyMHz(connector.currentFreqHz);
|
||||
final result = await _lineOfSightService.analyzePath(
|
||||
[start.point, end.point],
|
||||
startAntennaHeightMeters: startAntenna,
|
||||
endAntennaHeightMeters: endAntenna,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
if (!mounted) return;
|
||||
if (!_isRunRequestCurrent(
|
||||
|
|
@ -424,6 +428,12 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
|
|||
Widget _buildControlPanel(bool isImperial) {
|
||||
_sanitizeSelection();
|
||||
final segment = _primarySegmentResult();
|
||||
final connector = context.read<MeshCoreConnector>();
|
||||
final reportedFrequencyMHz = _normalizeFrequencyMHz(
|
||||
connector.currentFreqHz,
|
||||
);
|
||||
final displayFrequencyMHz = segment?.frequencyMHz ?? reportedFrequencyMHz;
|
||||
final kFactorUsed = segment?.usedKFactor;
|
||||
final endpoints = _visibleEndpoints();
|
||||
final distanceUnit = isImperial ? 'mi' : 'km';
|
||||
final heightUnit = isImperial ? 'ft' : 'm';
|
||||
|
|
@ -461,6 +471,9 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
|
|||
fontSize: 10,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
terrainLabel: context.l10n.losLegendTerrain,
|
||||
losBeamLabel: context.l10n.losLegendLosBeam,
|
||||
radioHorizonLabel: context.l10n.losLegendRadioHorizon,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -474,6 +487,14 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (segment != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
_LosLegend(
|
||||
terrainLabel: context.l10n.losLegendTerrain,
|
||||
losBeamLabel: context.l10n.losLegendLosBeam,
|
||||
radioHorizonLabel: context.l10n.losLegendRadioHorizon,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
segment != null
|
||||
|
|
@ -488,6 +509,52 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (displayFrequencyMHz != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2, bottom: 4),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
context.l10n.losFrequencyLabel,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey[700],
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'${displayFrequencyMHz.toStringAsFixed(3)} MHz',
|
||||
style: TextStyle(fontSize: 11, color: Colors.grey[700]),
|
||||
),
|
||||
if (kFactorUsed != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'k=${kFactorUsed.toStringAsFixed(3)}',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
icon: const Icon(Icons.info_outline, size: 16),
|
||||
color: Colors.grey[600],
|
||||
tooltip: context.l10n.losFrequencyInfoTooltip,
|
||||
onPressed: () {
|
||||
_showFrequencyInfoDialog(
|
||||
context,
|
||||
displayFrequencyMHz,
|
||||
kFactorUsed,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.l10n.losElevationAttribution,
|
||||
style: TextStyle(fontSize: 10, color: Colors.grey[700]),
|
||||
|
|
@ -896,6 +963,40 @@ class _LineOfSightMapScreenState extends State<LineOfSightMapScreen> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _showFrequencyInfoDialog(
|
||||
BuildContext context,
|
||||
double frequencyMHz,
|
||||
double kFactor,
|
||||
) {
|
||||
final baselineFreq = LineOfSightService.baselineFrequencyMHz;
|
||||
final baselineK = LineOfSightService.baselineKFactor;
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (dialogContext) => AlertDialog(
|
||||
title: Text(context.l10n.losFrequencyDialogTitle),
|
||||
content: Text(
|
||||
context.l10n.losFrequencyDialogDescription(
|
||||
baselineK,
|
||||
baselineFreq,
|
||||
frequencyMHz,
|
||||
kFactor,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogContext),
|
||||
child: Text(context.l10n.common_ok),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
double? _normalizeFrequencyMHz(int? frequencyKHz) {
|
||||
if (frequencyKHz == null || frequencyKHz <= 0) return null;
|
||||
return frequencyKHz / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
class _LosProfilePainter extends CustomPainter {
|
||||
|
|
@ -903,12 +1004,18 @@ class _LosProfilePainter extends CustomPainter {
|
|||
final String distanceUnit;
|
||||
final String heightUnit;
|
||||
final TextStyle badgeTextStyle;
|
||||
final String terrainLabel;
|
||||
final String losBeamLabel;
|
||||
final String radioHorizonLabel;
|
||||
|
||||
const _LosProfilePainter({
|
||||
required this.samples,
|
||||
required this.distanceUnit,
|
||||
required this.heightUnit,
|
||||
required this.badgeTextStyle,
|
||||
required this.terrainLabel,
|
||||
required this.losBeamLabel,
|
||||
required this.radioHorizonLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -920,44 +1027,108 @@ class _LosProfilePainter extends CustomPainter {
|
|||
if (samples.length < 2) return;
|
||||
|
||||
final minY = samples
|
||||
.map((s) => math.min(s.terrainMeters, s.lineHeightMeters))
|
||||
.map(
|
||||
(s) => math.min(
|
||||
math.min(s.terrainMeters, s.lineHeightMeters),
|
||||
s.refractedHeightMeters,
|
||||
),
|
||||
)
|
||||
.reduce(math.min);
|
||||
final maxY = samples
|
||||
.map((s) => math.max(s.terrainMeters, s.lineHeightMeters))
|
||||
.map(
|
||||
(s) => math.max(
|
||||
math.max(s.terrainMeters, s.lineHeightMeters),
|
||||
s.refractedHeightMeters,
|
||||
),
|
||||
)
|
||||
.reduce(math.max);
|
||||
final ySpan = math.max(1.0, maxY - minY);
|
||||
final maxDist = math.max(1.0, samples.last.distanceMeters);
|
||||
const horizontalPadding = 12.0;
|
||||
const verticalPadding = 12.0;
|
||||
final chartWidth = math.max(1.0, size.width - horizontalPadding * 2);
|
||||
final chartHeight = math.max(1.0, size.height - verticalPadding * 2);
|
||||
|
||||
Offset mapPoint(double x, double y) {
|
||||
final px = (x / maxDist) * size.width;
|
||||
final py = size.height - ((y - minY) / ySpan) * size.height;
|
||||
final px = horizontalPadding + (x / maxDist) * chartWidth;
|
||||
final py =
|
||||
size.height - verticalPadding - ((y - minY) / ySpan) * chartHeight;
|
||||
return Offset(px, py);
|
||||
}
|
||||
|
||||
final terrainPath = ui.Path();
|
||||
terrainPath.moveTo(0, size.height);
|
||||
for (final s in samples) {
|
||||
final p = mapPoint(s.distanceMeters, s.terrainMeters);
|
||||
final firstTerrainPoint = mapPoint(
|
||||
samples.first.distanceMeters,
|
||||
samples.first.terrainMeters,
|
||||
);
|
||||
final lastTerrainPoint = mapPoint(
|
||||
samples.last.distanceMeters,
|
||||
samples.last.terrainMeters,
|
||||
);
|
||||
|
||||
double distanceForCanvasX(double x) {
|
||||
final normalized = ((x - horizontalPadding) / chartWidth).clamp(0.0, 1.0);
|
||||
return normalized * maxDist;
|
||||
}
|
||||
|
||||
double elevationToPixel(double elevation) {
|
||||
final normalized = ((elevation - minY) / ySpan).clamp(0.0, 1.0);
|
||||
return size.height - verticalPadding - normalized * chartHeight;
|
||||
}
|
||||
|
||||
double extrapolateTerrain(double distance, bool isLeft) {
|
||||
final samplesForSlope = isLeft
|
||||
? samples.sublist(0, math.min(2, samples.length))
|
||||
: samples.sublist(samples.length - math.min(2, samples.length));
|
||||
if (samplesForSlope.length < 2) {
|
||||
return samplesForSlope.first.terrainMeters;
|
||||
}
|
||||
final a = samplesForSlope.first;
|
||||
final b = samplesForSlope.last;
|
||||
final dx = b.distanceMeters - a.distanceMeters;
|
||||
if (dx.abs() < 1e-6) return a.terrainMeters;
|
||||
final slope = (b.terrainMeters - a.terrainMeters) / dx;
|
||||
return a.terrainMeters + slope * (distance - a.distanceMeters);
|
||||
}
|
||||
|
||||
final leftDistance = distanceForCanvasX(0.0);
|
||||
final rightDistance = distanceForCanvasX(size.width);
|
||||
final leftEdgeTerrain = extrapolateTerrain(leftDistance, true);
|
||||
final rightEdgeTerrain = extrapolateTerrain(rightDistance, false);
|
||||
final leftEdgePoint = Offset(0.0, elevationToPixel(leftEdgeTerrain));
|
||||
final rightEdgePoint = Offset(
|
||||
size.width,
|
||||
elevationToPixel(rightEdgeTerrain),
|
||||
);
|
||||
|
||||
final terrainPath = ui.Path()
|
||||
..moveTo(0, size.height)
|
||||
..lineTo(leftEdgePoint.dx, leftEdgePoint.dy)
|
||||
..lineTo(firstTerrainPoint.dx, firstTerrainPoint.dy);
|
||||
for (final sample in samples) {
|
||||
final p = mapPoint(sample.distanceMeters, sample.terrainMeters);
|
||||
terrainPath.lineTo(p.dx, p.dy);
|
||||
}
|
||||
terrainPath.lineTo(size.width, size.height);
|
||||
terrainPath.close();
|
||||
terrainPath
|
||||
..lineTo(lastTerrainPoint.dx, lastTerrainPoint.dy)
|
||||
..lineTo(rightEdgePoint.dx, rightEdgePoint.dy)
|
||||
..lineTo(size.width, size.height)
|
||||
..close();
|
||||
|
||||
canvas.drawPath(terrainPath, Paint()..color = const Color(0xCC7C6F5D));
|
||||
const terrainFillColor = Color(0xCC7C6F5D);
|
||||
const terrainLineColor = Color(0xFF9FE870);
|
||||
const losLineColor = Color(0xFFE0E7FF);
|
||||
canvas.drawPath(terrainPath, Paint()..color = terrainFillColor);
|
||||
|
||||
final terrainLine = ui.Path();
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
final p = mapPoint(samples[i].distanceMeters, samples[i].terrainMeters);
|
||||
if (i == 0) {
|
||||
terrainLine.moveTo(p.dx, p.dy);
|
||||
} else {
|
||||
terrainLine.lineTo(p.dx, p.dy);
|
||||
}
|
||||
final terrainLine = ui.Path()..moveTo(leftEdgePoint.dx, leftEdgePoint.dy);
|
||||
for (final sample in samples) {
|
||||
final p = mapPoint(sample.distanceMeters, sample.terrainMeters);
|
||||
terrainLine.lineTo(p.dx, p.dy);
|
||||
}
|
||||
terrainLine.lineTo(rightEdgePoint.dx, rightEdgePoint.dy);
|
||||
canvas.drawPath(
|
||||
terrainLine,
|
||||
Paint()
|
||||
..color = const Color(0xFF9FE870)
|
||||
..color = terrainLineColor
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 2,
|
||||
);
|
||||
|
|
@ -977,10 +1148,59 @@ class _LosProfilePainter extends CustomPainter {
|
|||
canvas.drawPath(
|
||||
losLine,
|
||||
Paint()
|
||||
..color = const Color(0xFFE0E7FF)
|
||||
..color = losLineColor
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 2,
|
||||
);
|
||||
|
||||
const refractedLineColor = Color(0xFFFFD57F);
|
||||
final refractedLine = ui.Path();
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
final p = mapPoint(
|
||||
samples[i].distanceMeters,
|
||||
samples[i].refractedHeightMeters,
|
||||
);
|
||||
if (i == 0) {
|
||||
refractedLine.moveTo(p.dx, p.dy);
|
||||
} else {
|
||||
refractedLine.lineTo(p.dx, p.dy);
|
||||
}
|
||||
}
|
||||
canvas.drawPath(
|
||||
refractedLine,
|
||||
Paint()
|
||||
..color = refractedLineColor
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1.5,
|
||||
);
|
||||
|
||||
final capPath = ui.Path();
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
final p = mapPoint(
|
||||
samples[i].distanceMeters,
|
||||
samples[i].refractedHeightMeters,
|
||||
);
|
||||
if (i == 0) {
|
||||
capPath.moveTo(p.dx, p.dy);
|
||||
} else {
|
||||
capPath.lineTo(p.dx, p.dy);
|
||||
}
|
||||
}
|
||||
for (int i = samples.length - 1; i >= 0; i--) {
|
||||
final p = mapPoint(
|
||||
samples[i].distanceMeters,
|
||||
samples[i].lineHeightMeters,
|
||||
);
|
||||
capPath.lineTo(p.dx, p.dy);
|
||||
}
|
||||
capPath.close();
|
||||
const horizonFillColor = Color(0x40FFD57F);
|
||||
canvas.drawPath(
|
||||
capPath,
|
||||
Paint()
|
||||
..color = horizonFillColor
|
||||
..style = PaintingStyle.fill,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -988,7 +1208,10 @@ class _LosProfilePainter extends CustomPainter {
|
|||
return oldDelegate.samples != samples ||
|
||||
oldDelegate.distanceUnit != distanceUnit ||
|
||||
oldDelegate.heightUnit != heightUnit ||
|
||||
oldDelegate.badgeTextStyle != badgeTextStyle;
|
||||
oldDelegate.badgeTextStyle != badgeTextStyle ||
|
||||
oldDelegate.terrainLabel != terrainLabel ||
|
||||
oldDelegate.losBeamLabel != losBeamLabel ||
|
||||
oldDelegate.radioHorizonLabel != radioHorizonLabel;
|
||||
}
|
||||
|
||||
void _drawUnitBadge(Canvas canvas, Size size) {
|
||||
|
|
@ -1001,3 +1224,73 @@ class _LosProfilePainter extends CustomPainter {
|
|||
painter.paint(canvas, Offset(size.width - painter.width - 8, 8));
|
||||
}
|
||||
}
|
||||
|
||||
class _LosLegend extends StatelessWidget {
|
||||
static const _terrainColor = Color(0xFF9FE870);
|
||||
static const _losColor = Color(0xFFE0E7FF);
|
||||
static const _radioColor = Color(0xFFFFD57F);
|
||||
|
||||
final String terrainLabel;
|
||||
final String losBeamLabel;
|
||||
final String radioHorizonLabel;
|
||||
|
||||
const _LosLegend({
|
||||
required this.terrainLabel,
|
||||
required this.losBeamLabel,
|
||||
required this.radioHorizonLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textStyle =
|
||||
Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: Colors.white70,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
) ??
|
||||
const TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
);
|
||||
|
||||
final entries = [
|
||||
_LegendEntry(terrainLabel, _terrainColor),
|
||||
_LegendEntry(losBeamLabel, _losColor),
|
||||
_LegendEntry(radioHorizonLabel, _radioColor),
|
||||
];
|
||||
|
||||
const swatchSize = 10.0;
|
||||
|
||||
return Wrap(
|
||||
spacing: 16,
|
||||
runSpacing: 6,
|
||||
children: entries
|
||||
.map(
|
||||
(entry) => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: swatchSize,
|
||||
height: swatchSize,
|
||||
decoration: BoxDecoration(
|
||||
color: entry.color,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(entry.label, style: textStyle),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LegendEntry {
|
||||
final String label;
|
||||
final Color color;
|
||||
|
||||
const _LegendEntry(this.label, this.color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,14 @@ class LineOfSightSample {
|
|||
final double distanceMeters;
|
||||
final double terrainMeters;
|
||||
final double lineHeightMeters;
|
||||
final double refractedHeightMeters;
|
||||
final double clearanceMeters;
|
||||
|
||||
const LineOfSightSample({
|
||||
required this.distanceMeters,
|
||||
required this.terrainMeters,
|
||||
required this.lineHeightMeters,
|
||||
required this.refractedHeightMeters,
|
||||
required this.clearanceMeters,
|
||||
});
|
||||
}
|
||||
|
|
@ -30,6 +32,8 @@ class LineOfSightResult {
|
|||
final double? firstObstructionDistanceMeters;
|
||||
final List<LineOfSightSample> samples;
|
||||
final String? errorMessage;
|
||||
final double usedKFactor;
|
||||
final double? frequencyMHz;
|
||||
|
||||
const LineOfSightResult({
|
||||
required this.hasData,
|
||||
|
|
@ -38,12 +42,16 @@ class LineOfSightResult {
|
|||
required this.maxObstructionMeters,
|
||||
required this.firstObstructionDistanceMeters,
|
||||
required this.samples,
|
||||
required this.usedKFactor,
|
||||
this.frequencyMHz,
|
||||
this.errorMessage,
|
||||
});
|
||||
|
||||
const LineOfSightResult.error({
|
||||
required this.totalDistanceMeters,
|
||||
required this.errorMessage,
|
||||
this.usedKFactor = 4.0 / 3.0,
|
||||
this.frequencyMHz,
|
||||
}) : hasData = false,
|
||||
isClear = false,
|
||||
maxObstructionMeters = 0,
|
||||
|
|
@ -89,6 +97,11 @@ class LineOfSightService {
|
|||
static const Duration _cacheTtl = Duration(hours: 24);
|
||||
static const int _maxFetchAttempts = 4; // initial try + 3 retries
|
||||
static const Duration _initialBackoff = Duration(milliseconds: 300);
|
||||
static const double _baselineFrequencyMHz = 915.0;
|
||||
static const double _baselineKFactor = 4.0 / 3.0;
|
||||
|
||||
static double get baselineFrequencyMHz => _baselineFrequencyMHz;
|
||||
static double get baselineKFactor => _baselineKFactor;
|
||||
|
||||
final http.Client _httpClient;
|
||||
final bool _ownsHttpClient;
|
||||
|
|
@ -106,7 +119,7 @@ class LineOfSightService {
|
|||
List<LatLng> points, {
|
||||
double startAntennaHeightMeters = 1.5,
|
||||
double endAntennaHeightMeters = 1.5,
|
||||
double kFactor = 4.0 / 3.0,
|
||||
double? frequencyMHz,
|
||||
double obstructionToleranceMeters = 0.0,
|
||||
}) async {
|
||||
if (points.length < 2) {
|
||||
|
|
@ -123,6 +136,7 @@ class LineOfSightService {
|
|||
var blockedSegments = 0;
|
||||
var unknownSegments = 0;
|
||||
|
||||
final kFactor = _kFactorForFrequency(frequencyMHz);
|
||||
for (int i = 0; i < points.length - 1; i++) {
|
||||
final result = await analyzeLink(
|
||||
points[i],
|
||||
|
|
@ -130,6 +144,7 @@ class LineOfSightService {
|
|||
startAntennaHeightMeters: startAntennaHeightMeters,
|
||||
endAntennaHeightMeters: endAntennaHeightMeters,
|
||||
kFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
obstructionToleranceMeters: obstructionToleranceMeters,
|
||||
);
|
||||
segments.add(
|
||||
|
|
@ -163,7 +178,8 @@ class LineOfSightService {
|
|||
LatLng end, {
|
||||
double startAntennaHeightMeters = 1.5,
|
||||
double endAntennaHeightMeters = 1.5,
|
||||
double kFactor = 4.0 / 3.0,
|
||||
required double kFactor,
|
||||
double? frequencyMHz,
|
||||
double obstructionToleranceMeters = 0.0,
|
||||
}) async {
|
||||
final totalDistanceMeters = _distance.as(LengthUnit.Meter, start, end);
|
||||
|
|
@ -175,6 +191,8 @@ class LineOfSightService {
|
|||
maxObstructionMeters: 0,
|
||||
firstObstructionDistanceMeters: null,
|
||||
samples: const [],
|
||||
usedKFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -185,6 +203,8 @@ class LineOfSightService {
|
|||
return LineOfSightResult.error(
|
||||
totalDistanceMeters: totalDistanceMeters,
|
||||
errorMessage: errorElevationUnavailable,
|
||||
usedKFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -194,6 +214,7 @@ class LineOfSightService {
|
|||
startAntennaHeightMeters: startAntennaHeightMeters,
|
||||
endAntennaHeightMeters: endAntennaHeightMeters,
|
||||
kFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
obstructionToleranceMeters: obstructionToleranceMeters,
|
||||
);
|
||||
}
|
||||
|
|
@ -203,13 +224,16 @@ class LineOfSightService {
|
|||
required List<double> elevations,
|
||||
double startAntennaHeightMeters = 1.5,
|
||||
double endAntennaHeightMeters = 1.5,
|
||||
double kFactor = 4.0 / 3.0,
|
||||
required double kFactor,
|
||||
double? frequencyMHz,
|
||||
double obstructionToleranceMeters = 0.0,
|
||||
}) {
|
||||
if (points.length < 2 || elevations.length != points.length) {
|
||||
return const LineOfSightResult.error(
|
||||
return LineOfSightResult.error(
|
||||
totalDistanceMeters: 0,
|
||||
errorMessage: errorInvalidInput,
|
||||
usedKFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +262,10 @@ class LineOfSightService {
|
|||
(2 * effectiveEarthRadius);
|
||||
final terrainHeight = elevations[i] + earthBulge;
|
||||
final clearance = lineHeight - terrainHeight;
|
||||
final unrefBulge =
|
||||
(distanceFromStart * (totalDistanceMeters - distanceFromStart)) /
|
||||
(2 * _earthRadiusMeters);
|
||||
final refractedHeight = lineHeight + (unrefBulge - earthBulge);
|
||||
|
||||
if (clearance < -obstructionToleranceMeters) {
|
||||
isClear = false;
|
||||
|
|
@ -253,6 +281,7 @@ class LineOfSightService {
|
|||
distanceMeters: distanceFromStart,
|
||||
terrainMeters: terrainHeight,
|
||||
lineHeightMeters: lineHeight,
|
||||
refractedHeightMeters: refractedHeight,
|
||||
clearanceMeters: clearance,
|
||||
),
|
||||
);
|
||||
|
|
@ -265,9 +294,20 @@ class LineOfSightService {
|
|||
maxObstructionMeters: maxObstructionMeters,
|
||||
firstObstructionDistanceMeters: firstObstructionDistanceMeters,
|
||||
samples: samples,
|
||||
usedKFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
}
|
||||
|
||||
static double _kFactorForFrequency(double? frequencyMHz) {
|
||||
if (frequencyMHz == null) return _baselineKFactor;
|
||||
final delta =
|
||||
(frequencyMHz - _baselineFrequencyMHz) / _baselineFrequencyMHz;
|
||||
final adjustment = delta * 0.15;
|
||||
final scaled = _baselineKFactor * (1 + adjustment);
|
||||
return scaled.clamp(1.1, 1.6).toDouble();
|
||||
}
|
||||
|
||||
List<LatLng> _buildSamplePoints(
|
||||
LatLng start,
|
||||
LatLng end,
|
||||
|
|
|
|||
42
pubspec.lock
42
pubspec.lock
|
|
@ -347,6 +347,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.2.2"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
|
@ -597,6 +605,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_parsing
|
||||
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1010,6 +1026,30 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.2"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.19"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.13"
|
||||
vector_graphics_compiler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "5a88dd14c0954a5398af544651c7fb51b457a2a556949bfb25369b210ef73a74"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1043,7 +1083,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.3.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ void main() {
|
|||
elevations: elevations,
|
||||
startAntennaHeightMeters: 2,
|
||||
endAntennaHeightMeters: 2,
|
||||
kFactor: 4.0 / 3.0,
|
||||
);
|
||||
|
||||
expect(result.hasData, isTrue);
|
||||
|
|
@ -36,6 +37,7 @@ void main() {
|
|||
elevations: elevations,
|
||||
startAntennaHeightMeters: 1.5,
|
||||
endAntennaHeightMeters: 1.5,
|
||||
kFactor: 4.0 / 3.0,
|
||||
);
|
||||
|
||||
expect(result.hasData, isTrue);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue