Контур для ПУУД
This commit is contained in:
+1
@@ -28,6 +28,7 @@ data class AngularMotionCalculationResultDTO(
|
||||
val satelliteId: Long,
|
||||
val approximateTime: LocalDateTime,
|
||||
val startTime: LocalDateTime,
|
||||
val contourWkt: String?,
|
||||
val points: List<AngularMotionPointDTO>,
|
||||
)
|
||||
|
||||
|
||||
+6
@@ -10,6 +10,7 @@ import org.springframework.stereotype.Service
|
||||
import space.nstart.pcp.angularmotion.AngularMotionCalculatorFactory
|
||||
import space.nstart.pcp.angularmotion.AngularMotionConfig
|
||||
import space.nstart.pcp.angularmotion.AngularMotionMode
|
||||
import space.nstart.pcp.angularmotion.SurveyContourCalculator
|
||||
import space.nstart.pcp.angularmotion.SurveyId
|
||||
import space.nstart.pcp.pcp_request_service.configuration.CustomValidationException
|
||||
import space.nstart.pcp.pcp_request_service.service.SatelliteCatalogClient
|
||||
@@ -91,12 +92,14 @@ class AngularMotionService(
|
||||
} catch (error: RuntimeException) {
|
||||
throw CustomValidationException(error.message ?: "Ошибка расчета ПУУД")
|
||||
}
|
||||
val contourWkt = SurveyContourCalculator(EarthType.PZ90d02).calculate(result, request.captureAngleDeg)
|
||||
|
||||
return AngularMotionCalculationResultDTO(
|
||||
mode = result.mode,
|
||||
satelliteId = request.satelliteId,
|
||||
approximateTime = request.approximateTime,
|
||||
startTime = toDateTime(result.startTime),
|
||||
contourWkt = contourWkt,
|
||||
points = result.points.map { point ->
|
||||
AngularMotionPointDTO(
|
||||
time = toDateTime(point.t),
|
||||
@@ -122,6 +125,9 @@ class AngularMotionService(
|
||||
if (request.durationSec <= 0.0) {
|
||||
throw CustomValidationException("durationSec must be positive")
|
||||
}
|
||||
if (request.captureAngleDeg <= 0.0 || !request.captureAngleDeg.isFinite()) {
|
||||
throw CustomValidationException("captureAngleDeg must be positive")
|
||||
}
|
||||
if (request.latitudeDeg !in -90.0..90.0) {
|
||||
throw CustomValidationException("latitudeDeg must be in [-90; 90]")
|
||||
}
|
||||
|
||||
+55
-1
@@ -284,6 +284,54 @@
|
||||
});
|
||||
}
|
||||
|
||||
function polygonCoordinatesFromWkt(wkt) {
|
||||
const textValue = text(wkt).trim();
|
||||
const match = textValue.match(/^POLYGON\s*\(\((.*)\)\)$/i);
|
||||
if (!match) return [];
|
||||
|
||||
return match[1].split(',')
|
||||
.map(item => item.trim().split(/\s+/).map(Number))
|
||||
.filter(pair => pair.length >= 2 && Number.isFinite(pair[0]) && Number.isFinite(pair[1]))
|
||||
.map(pair => ({ lon: pair[0], lat: pair[1] }));
|
||||
}
|
||||
|
||||
function surveyContourBounds() {
|
||||
const coordinates = polygonCoordinatesFromWkt(state.result?.contourWkt);
|
||||
return {
|
||||
lats: coordinates.map(point => point.lat),
|
||||
lons: coordinates.map(point => point.lon),
|
||||
};
|
||||
}
|
||||
|
||||
function addSurveyContour() {
|
||||
if (!state.mapDataSource || !state.result?.contourWkt) return;
|
||||
const coordinates = polygonCoordinatesFromWkt(state.result.contourWkt);
|
||||
if (coordinates.length < 4) return;
|
||||
|
||||
const degrees = [];
|
||||
coordinates.forEach(point => {
|
||||
degrees.push(point.lon, point.lat);
|
||||
});
|
||||
const positions = Cesium.Cartesian3.fromDegreesArray(degrees);
|
||||
state.mapDataSource.entities.add({
|
||||
name: 'Контур съемки',
|
||||
polygon: {
|
||||
hierarchy: new Cesium.PolygonHierarchy(positions.slice(0, -1)),
|
||||
material: Cesium.Color.ORANGE.withAlpha(0.22),
|
||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||||
},
|
||||
});
|
||||
state.mapDataSource.entities.add({
|
||||
name: 'Граница контура съемки',
|
||||
polyline: {
|
||||
positions,
|
||||
width: 2,
|
||||
material: Cesium.Color.ORANGE,
|
||||
clampToGround: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function addTarget() {
|
||||
if (!state.mapDataSource) return;
|
||||
const lat = Number(el('angular-motion-lat').value);
|
||||
@@ -327,6 +375,9 @@
|
||||
if (Number.isFinite(value)) lons.push(value);
|
||||
});
|
||||
});
|
||||
const contourBounds = surveyContourBounds();
|
||||
lats.push(...contourBounds.lats);
|
||||
lons.push(...contourBounds.lons);
|
||||
if (lats.length === 0 || lons.length === 0) return;
|
||||
const minLat = Math.max(-89.0, Math.min(...lats) - 1.0);
|
||||
const maxLat = Math.min(89.0, Math.max(...lats) + 1.0);
|
||||
@@ -346,6 +397,7 @@
|
||||
addPolyline(points, 'leftLatitudeDeg', 'leftLongitudeDeg', Cesium.Color.CORNFLOWERBLUE.withAlpha(0.85), 2, 'Левая граница полосы');
|
||||
addPolyline(points, 'rightLatitudeDeg', 'rightLongitudeDeg', Cesium.Color.CORNFLOWERBLUE.withAlpha(0.85), 2, 'Правая граница полосы');
|
||||
addPolyline(points, 'latitudeDeg', 'longitudeDeg', Cesium.Color.YELLOW, 3, 'Трасса полета');
|
||||
addSurveyContour();
|
||||
addTarget();
|
||||
if (fit) fitMapToData();
|
||||
state.viewer.scene.requestRender();
|
||||
@@ -377,6 +429,7 @@
|
||||
longitudeDeg: Number(el('angular-motion-lon').value),
|
||||
heightM: Number(el('angular-motion-height').value || 0),
|
||||
durationSec: Number(el('angular-motion-duration').value),
|
||||
captureAngleDeg: Number(el('angular-motion-capture-angle').value || 1.5),
|
||||
leadAngleDeg: Number(el('angular-motion-lead-angle').value || 0),
|
||||
azimuthDeg: Number(el('angular-motion-azimuth').value || 0),
|
||||
pointInCenter: false,
|
||||
@@ -394,7 +447,7 @@
|
||||
state.result = result;
|
||||
const rows = Array.isArray(result?.points) ? result.points : [];
|
||||
el('angular-motion-result-meta').textContent = rows.length > 0
|
||||
? `Старт режима: ${formatDateTime(result.startTime)}. Точек: ${rows.length}.`
|
||||
? `Старт режима: ${formatDateTime(result.startTime)}. Точек: ${rows.length}. Контур: ${result?.contourWkt ? 'построен' : 'нет'}.`
|
||||
: 'Расчет не вернул точек.';
|
||||
el('angular-motion-export-csv').disabled = rows.length === 0;
|
||||
const body = el('angular-motion-result-body');
|
||||
@@ -420,6 +473,7 @@
|
||||
<td>${escapeHtml(formatNumber(point.sdi, 4))}</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
drawMap(true);
|
||||
}
|
||||
|
||||
async function calculate(event) {
|
||||
|
||||
@@ -78,10 +78,17 @@
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="angular-motion-capture-angle" class="form-label">Угол захвата, град</label>
|
||||
<input id="angular-motion-capture-angle" type="number" min="0.001" step="0.001" class="form-control" value="1.5" required>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="angular-motion-lead-angle" class="form-label">Упреждающий угол, град</label>
|
||||
<input id="angular-motion-lead-angle" type="number" step="0.001" class="form-control" value="0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-12 col-md-6 angular-motion-azimuth-field">
|
||||
<label for="angular-motion-azimuth" class="form-label">Азимут, град</label>
|
||||
<input id="angular-motion-azimuth" type="number" step="0.001" class="form-control" value="0">
|
||||
|
||||
Reference in New Issue
Block a user