Расчет средних ЗРВ

This commit is contained in:
emelianov
2026-05-28 16:47:43 +03:00
parent 2c65f412cf
commit 7dfa1163e9
5 changed files with 91 additions and 21 deletions
@@ -65,8 +65,11 @@ class RequestRestController {
@PostMapping("/station/{station_id}") @PostMapping("/station/{station_id}")
fun sat(@PathVariable("station_id") id : String, @RequestParam view : Boolean) = fun sat(
czmlService.station(id, view) @PathVariable("station_id") id : String,
@RequestParam view : Boolean,
@RequestParam(required = false) orbitHeightKm : Double?
) = czmlService.station(id, view, orbitHeightKm)
@@ -50,6 +50,7 @@ class CZMLService {
private val docStationName = "station_" private val docStationName = "station_"
private val entityStationName = "station_" private val entityStationName = "station_"
private val docReqCovName ="req_cov_" private val docReqCovName ="req_cov_"
private val DEFAULT_STATION_ORBIT_HEIGHT_KM = 500.0
@Autowired @Autowired
private lateinit var stationService: StationService private lateinit var stationService: StationService
@@ -378,9 +379,10 @@ private val docReqCovName ="req_cov_"
} }
fun station(id : String, view : Boolean) : Iterable<CZMLEntity>{ fun station(id : String, view : Boolean, orbitHeightKm: Double? = null) : Iterable<CZMLEntity>{
val req = stationService.station(id).block()?:return listOf() val req = stationService.station(id).block()?:return listOf()
val radius = ellipseAx( (500.0 * 1000.0), req.elevationMin * PI / 180) val normalizedOrbitHeightKm = orbitHeightKm?.takeIf { it > 0 } ?: DEFAULT_STATION_ORBIT_HEIGHT_KM
val radius = ellipseAx((normalizedOrbitHeightKm * 1000.0), req.elevationMin * PI / 180)
val r: MutableList<CZMLEntity> = mutableListOf(CZMLEntity("document", docStationName+id , "1.1")) val r: MutableList<CZMLEntity> = mutableListOf(CZMLEntity("document", docStationName+id , "1.1"))
r.add( r.add(
@@ -401,7 +403,7 @@ private val docReqCovName ="req_cov_"
extrudedHeight = 1000.0, extrudedHeight = 1000.0,
height = 1000.0 height = 1000.0
), ),
description = "Станция ${req.name}", description = "Станция ${req.name}<br>Высота орбиты для зоны видимости: ${normalizedOrbitHeightKm} км",
model = CZMLModel( model = CZMLModel(
gltf = "/model/station.glb", gltf = "/model/station.glb",
show = !view show = !view
@@ -79,7 +79,8 @@
checkModels(); checkModels();
} else{ } else{
var sceneMode = (viewer.scene.mode == Cesium.SceneMode.SCENE2D); var sceneMode = (viewer.scene.mode == Cesium.SceneMode.SCENE2D);
var u = '/requests/station/'+req.id+'?view='+sceneMode var u = '/requests/station/'+req.id+'?view='+sceneMode+
'&orbitHeightKm='+encodeURIComponent(selectedStationOrbitHeightKm())
fetch(u, { fetch(u, {
method: "post", method: "post",
headers: { headers: {
@@ -115,6 +116,16 @@
} }
} }
function selectedStationOrbitHeightKm() {
const input = document.getElementById('stationOrbitHeightKm');
const value = Number(input?.value || 500);
if (!Number.isFinite(value) || value <= 0) {
if (input) input.value = '500';
return 500;
}
return value;
}
function drawSat(show, req, startInput, endInput, runId){ function drawSat(show, req, startInput, endInput, runId){
if (req){ if (req){
@@ -292,6 +292,16 @@
<input class="form-check-input" type="checkbox" id="toggleCoverage"> <input class="form-check-input" type="checkbox" id="toggleCoverage">
<label class="form-check-label" for="toggleCoverage">Показать зоны покрытия</label> <label class="form-check-label" for="toggleCoverage">Показать зоны покрытия</label>
</div> </div>
<div class="mb-2">
<label for="stationOrbitHeightKm" class="form-label form-label-sm mb-1">Высота орбиты, км</label>
<input type="number"
class="form-control form-control-sm"
id="stationOrbitHeightKm"
min="1"
step="1"
value="500"
onchange="handleStationOrbitHeightChange()">
</div>
<select class="form-select form-select-sm mb-2"> <select class="form-select form-select-sm mb-2">
<option selected>Все типы станций</option> <option selected>Все типы станций</option>
<option value="1">Наземные</option> <option value="1">Наземные</option>
@@ -1712,6 +1722,13 @@
} }
} }
function handleStationOrbitHeightChange() {
document.querySelectorAll('#stationsTableBody input[type="checkbox"]:checked').forEach(function(checkbox) {
checkStation(false, checkbox.value);
checkStation(true, checkbox.value);
});
}
// Функция для обработки запросов // Функция для обработки запросов
function checkOrbit(show, sat_id) { function checkOrbit(show, sat_id) {
@@ -10,6 +10,8 @@ import org.springframework.boot.test.web.server.LocalServerPort
import org.springframework.test.context.bean.override.mockito.MockitoBean import org.springframework.test.context.bean.override.mockito.MockitoBean
import org.springframework.web.reactive.function.client.WebClient import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PositionDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign
import space.nstart.pcp.pcp_types_lib.dto.ballistics.StationDTO import space.nstart.pcp.pcp_types_lib.dto.ballistics.StationDTO
import space.nstart.pcp.pcp_types_lib.dto.requests.ComplexPlanProcessRequestDTO import space.nstart.pcp.pcp_types_lib.dto.requests.ComplexPlanProcessRequestDTO
@@ -61,6 +63,18 @@ class MapControllerComplexPlanTest {
private val objectMapper = ObjectMapper() private val objectMapper = ObjectMapper()
private fun stationEllipseRadius(stationId: String, orbitHeightKm: Double): Double {
val actual = WebClient.create("http://localhost:$port")
.post()
.uri("/requests/station/$stationId?view=true&orbitHeightKm=$orbitHeightKm")
.retrieve()
.bodyToMono(String::class.java)
.map(objectMapper::readTree)
.block()!!
return actual[1]["ellipse"]["semiMajorAxis"].asDouble()
}
@Test @Test
fun `local post api requests delegates to earth service facade`() { fun `local post api requests delegates to earth service facade`() {
val responseId = UUID.fromString("11111111-1111-4111-8111-111111111111") val responseId = UUID.fromString("11111111-1111-4111-8111-111111111111")
@@ -256,11 +270,34 @@ class MapControllerComplexPlanTest {
.block()!! .block()!!
assertTrue(body.contains("cesiumContainer")) assertTrue(body.contains("cesiumContainer"))
assertTrue(body.contains("stationOrbitHeightKm"))
assertTrue(body.contains("Высота орбиты, км"))
assertTrue(body.contains("dynamic_plan_map_layers.js")) assertTrue(body.contains("dynamic_plan_map_layers.js"))
assertTrue(body.contains("PcpDynamicPlanMapLayers")) assertTrue(body.contains("PcpDynamicPlanMapLayers"))
verify(earthService).reqs() verify(earthService).reqs()
} }
@Test
fun `station czml endpoint uses orbit height for visibility zone`() {
val stationId = "11111111-1111-4111-8111-111111111111"
doReturn(
Mono.just(
StationDTO(
id = UUID.fromString(stationId),
number = 1,
name = "Station 1",
position = PositionDTO(lat = 55.0, long = 37.0, height = 200.0),
elevationMin = 5.0
)
)
).`when`(stationService).station(stationId)
val baseRadius = stationEllipseRadius(stationId, 500.0)
val higherOrbitRadius = stationEllipseRadius(stationId, 700.0)
assertTrue(higherOrbitRadius > baseRadius)
}
@Test @Test
fun `dynamic plan map layer keeps only one visible run`() { fun `dynamic plan map layer keeps only one visible run`() {
val body = WebClient.create("http://localhost:$port") val body = WebClient.create("http://localhost:$port")