fix: reuse main page pass list for mutual search
findMutualPasses was computing passes independently with its own search algorithm, which produced different results from the main page's getLeoPass. Now it directly reuses satelliteRepo.passes, which is the same list shown on the main passes page. The only additional computation is refining the common window for station B and sampling elevation/azimuth curves.
This commit is contained in:
1 parent
43788ba7a7
commit
86ee3dcbac
1 file changed
+48
-51
+48
-51
@@ -210,63 +210,60 @@ class MutualViewModel(
|
||||
val endTime = time + hours * 60L * 60L * 1000L
|
||||
val sampleInterval = 5_000L // 5 seconds between samples for smooth curves
|
||||
|
||||
for (sat in satellites) {
|
||||
if (sat.data.meanmo < 1e-8) continue
|
||||
var searchStart = time
|
||||
// Find ALL mutual passes for this satellite
|
||||
while (true) {
|
||||
val t = findNextMutualPass(sat, posA, posB, searchStart, endTime)
|
||||
if (t == null) break
|
||||
val (aos, los) = t
|
||||
// Reuse the main page's pass list (calculated by getLeoPass/getGeoPass)
|
||||
// so the mutual pass times match the main page exactly.
|
||||
val existingPasses = satelliteRepo.passes.value
|
||||
for (pass in existingPasses) {
|
||||
if (pass.losTime <= time || pass.aosTime >= endTime) continue
|
||||
if (pass.isDeepSpace) continue
|
||||
if (pass.orbitalObject.data.meanmo < 1e-8) continue
|
||||
|
||||
// Refine AOS: finer search near the edge (0° horizon, like the main radar)
|
||||
val refinedAos = refineEdge(sat, posA, posB, aos, step = 1_000L, goingUp = true)
|
||||
// Refine LOS: finer search near the edge
|
||||
val refinedLos = refineEdge(sat, posA, posB, los, step = 1_000L, goingUp = false)
|
||||
val sat = pass.orbitalObject
|
||||
// Refine the common window: AOS = max(A's AOS, B's horizon crossing)
|
||||
val refinedAos = refineEdge(sat, posA, posB, pass.aosTime, 1_000L, goingUp = true)
|
||||
val refinedLos = refineEdge(sat, posA, posB, pass.losTime, 1_000L, goingUp = false)
|
||||
if (refinedLos <= refinedAos) continue
|
||||
|
||||
val samples = mutableListOf<Pair<Long, Pair<Double, Double>>>()
|
||||
val tracks = mutableListOf<TrackSample>()
|
||||
var maxElevA = 0.0
|
||||
var maxElevB = 0.0
|
||||
val samples = mutableListOf<Pair<Long, Pair<Double, Double>>>()
|
||||
val tracks = mutableListOf<TrackSample>()
|
||||
var maxElevA = 0.0
|
||||
var maxElevB = 0.0
|
||||
|
||||
var tSample = refinedAos
|
||||
while (tSample <= refinedLos) {
|
||||
val fullA = sat.getFullPosition(posA, tSample)
|
||||
val fullB = sat.getFullPosition(posB, tSample)
|
||||
val elevA = fullA.elevation * 180.0 / PI
|
||||
val elevB = fullB.elevation * 180.0 / PI
|
||||
if (elevA > maxElevA) maxElevA = elevA
|
||||
if (elevB > maxElevB) maxElevB = elevB
|
||||
samples.add(tSample to (elevA to elevB))
|
||||
tracks.add(
|
||||
TrackSample(
|
||||
time = tSample,
|
||||
azimuthA = fullA.azimuth * 180.0 / PI,
|
||||
elevationA = elevA,
|
||||
azimuthB = fullB.azimuth * 180.0 / PI,
|
||||
elevationB = elevB
|
||||
)
|
||||
var tSample = refinedAos
|
||||
while (tSample <= refinedLos) {
|
||||
val fullA = sat.getFullPosition(posA, tSample)
|
||||
val fullB = sat.getFullPosition(posB, tSample)
|
||||
val elevA = fullA.elevation * 180.0 / PI
|
||||
val elevB = fullB.elevation * 180.0 / PI
|
||||
if (elevA > maxElevA) maxElevA = elevA
|
||||
if (elevB > maxElevB) maxElevB = elevB
|
||||
samples.add(tSample to (elevA to elevB))
|
||||
tracks.add(
|
||||
TrackSample(
|
||||
time = tSample,
|
||||
azimuthA = fullA.azimuth * 180.0 / PI,
|
||||
elevationA = elevA,
|
||||
azimuthB = fullB.azimuth * 180.0 / PI,
|
||||
elevationB = elevB
|
||||
)
|
||||
tSample += sampleInterval
|
||||
}
|
||||
)
|
||||
tSample += sampleInterval
|
||||
}
|
||||
|
||||
// Both stations must reach their own min elevation for a usable mutual pass
|
||||
if (maxElevA > minElevADeg && maxElevB > minElevBDeg) {
|
||||
results.add(
|
||||
MutualPass(
|
||||
catNum = sat.data.catnum,
|
||||
name = sat.data.name,
|
||||
startTime = refinedAos,
|
||||
endTime = refinedLos,
|
||||
maxElevationA = (maxElevA * 10).roundToInt() / 10.0,
|
||||
maxElevationB = (maxElevB * 10).roundToInt() / 10.0,
|
||||
elevationSamples = samples,
|
||||
trackSamples = tracks
|
||||
)
|
||||
// Both stations must reach their own min elevation for a usable mutual pass
|
||||
if (maxElevA > minElevADeg && maxElevB > minElevBDeg) {
|
||||
results.add(
|
||||
MutualPass(
|
||||
catNum = pass.catNum,
|
||||
name = pass.orbitalObject.data.name,
|
||||
startTime = refinedAos,
|
||||
endTime = refinedLos,
|
||||
maxElevationA = (maxElevA * 10).roundToInt() / 10.0,
|
||||
maxElevationB = (maxElevB * 10).roundToInt() / 10.0,
|
||||
elevationSamples = samples,
|
||||
trackSamples = tracks
|
||||
)
|
||||
}
|
||||
// Advance past this pass and keep searching
|
||||
searchStart = refinedLos + 120_000L
|
||||
)
|
||||
}
|
||||
}
|
||||
return results
|
||||
|
||||
Reference in new issue
Block a user