mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
fix: smooth dual-station elevation curve
- Fix cubic Bezier control points (proper Catmull-Rom to Bezier conversion) - Refine AOS/LOS more robustly by walking from edge into the pass window - Still 5s sampling for smooth curves
This commit is contained in:
1 parent
5de370983d
commit
d7e1ce11c9
9 files changed
+437
-221
No files matched your search
@@ -5,3 +5,7 @@ plugins {
|
||||
android {
|
||||
namespace = "com.rtbishop.look4sat.feature.radar"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":feature:mutual"))
|
||||
}
|
||||
@@ -59,6 +59,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
|
||||
import com.rtbishop.look4sat.core.domain.repository.IContainerProvider
|
||||
import com.rtbishop.look4sat.core.domain.repository.MutualPassData
|
||||
import com.rtbishop.look4sat.core.domain.utility.toDegrees
|
||||
import com.rtbishop.look4sat.core.presentation.EmptyListCard
|
||||
import com.rtbishop.look4sat.core.presentation.IconCard
|
||||
@@ -70,6 +71,7 @@ import com.rtbishop.look4sat.core.presentation.formatFrequency
|
||||
import com.rtbishop.look4sat.core.presentation.getDefaultPass
|
||||
import com.rtbishop.look4sat.core.presentation.isVerticalLayout
|
||||
import com.rtbishop.look4sat.core.presentation.layoutPadding
|
||||
import com.rtbishop.look4sat.feature.mutual.ElevationCurveChart
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private enum class RadarPage(val title: String) {
|
||||
@@ -83,6 +85,7 @@ fun RadarDestination(navigateUp: () -> Unit) {
|
||||
val container = (context.applicationContext as IContainerProvider).getMainContainer()
|
||||
val viewModel: RadarViewModel = viewModel(factory = RadarViewModel.factory(container))
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
val mutualData by container.mutualPassData.collectAsStateWithLifecycle()
|
||||
// Sync actual permission state on every recomposition so it survives screen re-entry
|
||||
val hasPermission = ContextCompat.checkSelfPermission(
|
||||
context, Manifest.permission.RECORD_AUDIO
|
||||
@@ -97,7 +100,7 @@ fun RadarDestination(navigateUp: () -> Unit) {
|
||||
viewModel.onAction(RadarAction.SstvPermissionResult(granted))
|
||||
viewModel.onAction(RadarAction.CwPermissionResult(granted))
|
||||
}
|
||||
RadarScreen(uiState, viewModel::onAction, navigateUp, requestMicPermission = {
|
||||
RadarScreen(uiState, viewModel::onAction, navigateUp, mutualData, requestMicPermission = {
|
||||
permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
|
||||
})
|
||||
}
|
||||
@@ -107,6 +110,7 @@ private fun RadarScreen(
|
||||
uiState: RadarState,
|
||||
onAction: (RadarAction) -> Unit,
|
||||
navigateUp: () -> Unit,
|
||||
mutualData: MutualPassData,
|
||||
requestMicPermission: () -> Unit
|
||||
) {
|
||||
val upcomingPass = uiState.currentPass ?: getDefaultPass()
|
||||
@@ -137,10 +141,16 @@ private fun RadarScreen(
|
||||
}
|
||||
if (isVertical) {
|
||||
RadarCard(uiState, Modifier.weight(1f))
|
||||
if (mutualData.samples.isNotEmpty()) {
|
||||
MutualElevationCard(mutualData, Modifier.weight(1f))
|
||||
}
|
||||
PagerCard(uiState, onAction, requestMicPermission, Modifier.weight(1f))
|
||||
} else {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
RadarCard(uiState, Modifier.weight(1f))
|
||||
if (mutualData.samples.isNotEmpty()) {
|
||||
MutualElevationCard(mutualData, Modifier.weight(1f))
|
||||
}
|
||||
PagerCard(uiState, onAction, requestMicPermission, Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
@@ -304,3 +314,19 @@ private fun RadarLabel(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MutualElevationCard(mutualData: MutualPassData, modifier: Modifier = Modifier) {
|
||||
ElevatedCard(modifier = modifier) {
|
||||
Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {
|
||||
if (mutualData.samples.isNotEmpty()) {
|
||||
ElevationCurveChart(
|
||||
samples = mutualData.samples,
|
||||
startTime = mutualData.startTime,
|
||||
endTime = mutualData.endTime,
|
||||
maxElev = mutualData.maxElev
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,13 @@ data class RadarState(
|
||||
val transceivers: TransceiverSubState = TransceiverSubState(),
|
||||
val radioControl: RadioControlSubState = RadioControlSubState(),
|
||||
val sstv: SstvSubState = SstvSubState(),
|
||||
val cw: CwSubState = CwSubState()
|
||||
val cw: CwSubState = CwSubState(),
|
||||
val mutualSamples: List<Pair<Long, Pair<Double, Double>>> = emptyList(),
|
||||
val mutualStartTime: Long = 0L,
|
||||
val mutualEndTime: Long = 0L,
|
||||
val mutualMaxElev: Double = 10.0,
|
||||
val mutualLabelA: String = "你",
|
||||
val mutualLabelB: String = "友台"
|
||||
)
|
||||
|
||||
enum class SstvStatus { Idle, Recording }
|
||||
|
||||
Reference in new issue
Block a user