diff --git a/frontend/src/components/SearchMap.jsx b/frontend/src/components/SearchMap.jsx
index ccc96c1..060bd05 100644
--- a/frontend/src/components/SearchMap.jsx
+++ b/frontend/src/components/SearchMap.jsx
@@ -15,9 +15,9 @@ const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones, waterFeatures }) => {
const tnpPosition = [tnpLat || 53.9, tnpLon || 27.56];
const distance = maxDistance || 5.0;
- // Функция для создания точек сектора
- const createSectorPoints = (centerLat, centerLon, radiusKm, startAngle, endAngle, points = 20) => {
- const coords = [[centerLat, centerLon]]; // Начинаем с центра
+ // Функция для создания точек дуги
+ const createArcPoints = (centerLat, centerLon, radiusKm, startAngle, endAngle, points = 24) => {
+ const coords = [];
// Конвертируем км в градусы (приблизительно)
const latPerKm = 1 / 111.0;
@@ -34,9 +34,15 @@ const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones, waterFeatures }) => {
coords.push([lat, lon]);
}
- coords.push([centerLat, centerLon]); // Замыкаем в центре
return coords;
};
+
+ // Функция для создания точек сектора (пирог: дуга + центр)
+ const createSectorPoints = (centerLat, centerLon, radiusKm, startAngle, endAngle, points = 24) => {
+ return [[centerLat, centerLon],
+ ...createArcPoints(centerLat, centerLon, radiusKm, startAngle, endAngle, points),
+ [centerLat, centerLon]];
+ };
// Направления и их углы
const directionAngles = {
@@ -50,45 +56,41 @@ const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones, waterFeatures }) => {
'NW': 315
};
- // Создаем секторы на основе зон
- const sectors = zones && zones.length > 0 ? zones.slice(0, 8).map((zone, idx) => {
- const angle = directionAngles[zone.direction] || 0;
- const startAngle = angle - 22.5; // ±22.5° = 45° сектор
+ // Подсветка приоритетных направлений: 45°-сектор ПОЛНОГО радиуса поверх кругов.
+ // Приоритет задаёт прозрачность (топ-зона заметнее), цвет — палитра ЦОУ.
+ const highlightSectors = zones && zones.length > 0 ? zones.map((zone, idx) => {
+ const angle = directionAngles[zone.direction];
+ if (angle === undefined) return null;
+ const startAngle = angle - 22.5;
const endAngle = angle + 22.5;
- // Определяем радиус на основе score
- let radius = distance;
- if (zone.score >= 90) radius = distance * 1.0;
- else if (zone.score >= 70) radius = distance * 0.8;
- else if (zone.score >= 50) radius = distance * 0.6;
- else radius = distance * 0.4;
-
- // Цвет на основе приоритета
let color, fillOpacity;
if (idx === 0) {
color = '#ff4d00';
- fillOpacity = 0.35;
+ fillOpacity = 0.30;
} else if (idx === 1) {
color = '#ff9f1a';
- fillOpacity = 0.25;
+ fillOpacity = 0.22;
} else if (idx === 2) {
color = '#ffd166';
- fillOpacity = 0.2;
+ fillOpacity = 0.18;
} else {
color = '#8b949e';
- fillOpacity = 0.1;
+ fillOpacity = 0.10;
}
return {
- points: createSectorPoints(tnpPosition[0], tnpPosition[1], radius, startAngle, endAngle),
+ points: createSectorPoints(tnpPosition[0], tnpPosition[1], distance, startAngle, endAngle),
color,
fillOpacity,
+ weight: idx < 3 ? 2 : 1,
zone
};
- }) : [];
+ }).filter(Boolean) : [];
- // Если зон нет, создаем базовые концентрические круги
- const createCirclePoints = (centerLat, centerLon, radiusKm, points = 40) => {
+ // Концентрические круги — возможная зона поиска (базовый слой).
+ // Классика ПСО: ядро (0.5R) — наибольшая плотность вероятности.
+ const createCirclePoints = (centerLat, centerLon, radiusKm, points = 48) => {
const coords = [];
const latPerKm = 1 / 111.0;
const lonPerKm = 1 / (111.0 * Math.cos(centerLat * Math.PI / 180));
@@ -107,23 +109,23 @@ const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones, waterFeatures }) => {
{
points: createCirclePoints(tnpPosition[0], tnpPosition[1], distance),
color: '#ffd166',
- fillOpacity: 0.15,
- label: `Зона 3 (${distance.toFixed(1)} км)`,
- probability: 10
+ fillOpacity: 0.12,
+ label: `Внешняя зона (до ${distance.toFixed(1)} км)`,
+ probability: 'низкая'
},
{
points: createCirclePoints(tnpPosition[0], tnpPosition[1], distance * 0.75),
color: '#ff9f1a',
- fillOpacity: 0.2,
- label: `Зона 2 (${(distance * 0.75).toFixed(1)} км)`,
- probability: 20
+ fillOpacity: 0.16,
+ label: `Средняя зона (до ${(distance * 0.75).toFixed(1)} км)`,
+ probability: 'средняя'
},
{
points: createCirclePoints(tnpPosition[0], tnpPosition[1], distance * 0.5),
color: '#ff4d00',
- fillOpacity: 0.3,
- label: `Зона 1 (${(distance * 0.5).toFixed(1)} км)`,
- probability: 70
+ fillOpacity: 0.20,
+ label: `Ядро зоны (до ${(distance * 0.5).toFixed(1)} км)`,
+ probability: 'высокая'
}
];
@@ -192,46 +194,46 @@ const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones, waterFeatures }) => {
))}
- {/* Рисуем секторы или круги */}
- {sectors.length > 0 ? (
- sectors.map((sector, idx) => (
-
-
- #{idx + 1} {sector.zone.name}
- Направление: {sector.zone.direction}
- Приоритет: {sector.zone.score}%
- {sector.zone.reasoning}
-
-
- ))
- ) : (
- defaultZones.map((zone, idx) => (
-
-
- {zone.label}
- Вероятность: {zone.probability}%
-
-
- ))
- )}
+ {/* Базовый слой: концентрические круги возможной зоны поиска */}
+ {defaultZones.map((zone, idx) => (
+
+
+ {zone.label}
+ Плотность вероятности: {zone.probability}
+
+
+ ))}
+
+ {/* Подсветка приоритетных направлений (поверх кругов) */}
+ {highlightSectors.map((sector, idx) => (
+
+
+ #{idx + 1} {sector.zone.name}
+ Направление: {sector.zone.direction}
+ Приоритет: {sector.zone.score}%
+ {sector.zone.reasoning}
+
+
+ ))}
{/* ТНП - красный маркер */}