generated from Grigo/AndroidTemplate
feat: новая архитектура UI и расширенная визуализация AIS
Архитектурные улучшения: - Внедрен UIRenderingCoordinator с централизованным throttling - Решены проблемы зависания UI через батчинг операций карты - Добавлен VesselPathController для отслеживания маршрутов - Реализован MapLibreMapImpl как альтернатива Яндекс.Картам Визуализация AIS: - Добавлены векторные иконки для всех типов судов - Разделение Class A/B судов с соответствующими иконками - Иконки навигационных статусов (anchor, moored, engine, sail) - Улучшенный CursorOverlay с информацией о судах Производительность: - Throttling UI обновлений (vessel: 500ms, AIS: 1s, paths: 2s) - Устранение утечек Handler объектов - Оптимизация GeoJSON операций в MapLibre
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.grigowashere.aismap.maps;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import com.yandex.mapkit.geometry.Point;
|
||||
import com.yandex.mapkit.map.MapObjectCollection;
|
||||
import com.yandex.mapkit.map.PolylineMapObject;
|
||||
@@ -16,6 +17,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
*/
|
||||
public class VesselPathTracker {
|
||||
|
||||
private static final String TAG = "VesselPathTracker";
|
||||
private static final int MAX_PATH_POINTS = 100; // Максимальное количество точек в пути
|
||||
private static final long MIN_TIME_BETWEEN_POINTS = 1000; // Минимальное время между точками (1 секунда)
|
||||
private static final double MIN_DISTANCE_BETWEEN_POINTS = 10.0; // Минимальное расстояние между точками (10 метров)
|
||||
@@ -58,6 +60,7 @@ public class VesselPathTracker {
|
||||
this.mapObjects = mapObjects;
|
||||
this.pathHistory = new ConcurrentLinkedQueue<>();
|
||||
this.lastUpdateTime = 0;
|
||||
Log.d(TAG, "Created VesselPathTracker for vessel: " + vesselId + ", mapObjects: " + (mapObjects != null ? "not null" : "null"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,12 +68,17 @@ public class VesselPathTracker {
|
||||
*/
|
||||
public void updatePosition(double latitude, double longitude, double speed, double course) {
|
||||
if (!isEnabled) {
|
||||
Log.d(TAG, "VesselPathTracker disabled for vessel: " + vesselId);
|
||||
return;
|
||||
}
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
Point newPosition = new Point(latitude, longitude);
|
||||
|
||||
Log.d(TAG, "updatePosition called for vessel: " + vesselId +
|
||||
", lat: " + latitude + ", lon: " + longitude +
|
||||
", speed: " + speed + ", course: " + course);
|
||||
|
||||
// Проверяем, нужно ли добавить новую точку
|
||||
if (shouldAddPoint(newPosition, currentTime)) {
|
||||
PathPoint newPoint = new PathPoint(newPosition, currentTime, speed, course);
|
||||
@@ -84,8 +92,14 @@ public class VesselPathTracker {
|
||||
lastPosition = newPosition;
|
||||
lastUpdateTime = currentTime;
|
||||
|
||||
Log.d(TAG, "Added new point to path for vessel: " + vesselId +
|
||||
", total points: " + pathHistory.size());
|
||||
|
||||
// Обновляем отображение пути
|
||||
updatePathDisplay();
|
||||
} else {
|
||||
Log.d(TAG, "Point not added for vessel: " + vesselId +
|
||||
" (time or distance filter)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,10 +127,14 @@ public class VesselPathTracker {
|
||||
* Обновляет отображение пути на карте
|
||||
*/
|
||||
private void updatePathDisplay() {
|
||||
Log.d(TAG, "updatePathDisplay called for vessel: " + vesselId);
|
||||
|
||||
if (pathHistory.isEmpty()) {
|
||||
Log.d(TAG, "Path history is empty for vessel: " + vesselId);
|
||||
return;
|
||||
}
|
||||
if (mapObjects == null) {
|
||||
Log.d(TAG, "MapObjects is null for vessel: " + vesselId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,17 +144,22 @@ public class VesselPathTracker {
|
||||
pathPoints.add(point.position);
|
||||
}
|
||||
|
||||
Log.d(TAG, "Creating path line with " + pathPoints.size() + " points for vessel: " + vesselId);
|
||||
|
||||
// Удаляем старые линии
|
||||
try {
|
||||
if (pathLine != null) {
|
||||
Log.d(TAG, "Removing old path line for vessel: " + vesselId);
|
||||
mapObjects.remove(pathLine);
|
||||
pathLine = null;
|
||||
}
|
||||
if (predictionLine != null) {
|
||||
Log.d(TAG, "Removing old prediction line for vessel: " + vesselId);
|
||||
mapObjects.remove(predictionLine);
|
||||
predictionLine = null;
|
||||
}
|
||||
} catch (RuntimeException ignored) {
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "Error removing old lines for vessel: " + vesselId, e);
|
||||
// Коллекция могла быть инвалидирована (weak_ptr expired). Прекращаем обновления.
|
||||
isEnabled = false;
|
||||
return;
|
||||
@@ -145,15 +168,25 @@ public class VesselPathTracker {
|
||||
// Создаем линию пройденного пути
|
||||
if (pathPoints.size() > 1) {
|
||||
try {
|
||||
Log.d(TAG, "Adding new path line for vessel: " + vesselId);
|
||||
pathLine = mapObjects.addPolyline(new com.yandex.mapkit.geometry.Polyline(pathPoints));
|
||||
if (pathLine != null) {
|
||||
pathLine.setStrokeColor(pathColor);
|
||||
pathLine.setStrokeWidth(pathWidth);
|
||||
Log.d(TAG, "Path line created successfully for vessel: " + vesselId +
|
||||
", color: " + Integer.toHexString(pathColor) +
|
||||
", width: " + pathWidth);
|
||||
} else {
|
||||
Log.e(TAG, "Failed to create path line for vessel: " + vesselId);
|
||||
}
|
||||
} catch (RuntimeException ignored) {
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "Error creating path line for vessel: " + vesselId, e);
|
||||
isEnabled = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Not enough points for path line for vessel: " + vesselId +
|
||||
" (need at least 2, have " + pathPoints.size() + ")");
|
||||
}
|
||||
|
||||
// Создаем линию прогнозируемого движения
|
||||
@@ -164,10 +197,14 @@ public class VesselPathTracker {
|
||||
* Создает линию прогнозируемого движения
|
||||
*/
|
||||
private void createPredictionLine() {
|
||||
Log.d(TAG, "createPredictionLine called for vessel: " + vesselId);
|
||||
|
||||
if (pathHistory.isEmpty()) {
|
||||
Log.d(TAG, "Path history is empty for prediction line for vessel: " + vesselId);
|
||||
return;
|
||||
}
|
||||
if (mapObjects == null) {
|
||||
Log.d(TAG, "MapObjects is null for prediction line for vessel: " + vesselId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -178,6 +215,9 @@ public class VesselPathTracker {
|
||||
}
|
||||
|
||||
if (lastPoint == null || lastPoint.speed <= 0) {
|
||||
Log.d(TAG, "Cannot create prediction line for vessel: " + vesselId +
|
||||
" (lastPoint: " + (lastPoint != null ? "not null" : "null") +
|
||||
", speed: " + (lastPoint != null ? lastPoint.speed : "N/A") + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -185,6 +225,11 @@ public class VesselPathTracker {
|
||||
double predictionTimeMinutes = 1.0; // 1 минута
|
||||
double predictionDistance = lastPoint.speed * predictionTimeMinutes * 60.0; // расстояние в метрах
|
||||
|
||||
Log.d(TAG, "Creating prediction line for vessel: " + vesselId +
|
||||
", speed: " + lastPoint.speed +
|
||||
", course: " + lastPoint.course +
|
||||
", prediction distance: " + predictionDistance + "m");
|
||||
|
||||
// Конвертируем курс в радианы
|
||||
double courseRad = Math.toRadians(lastPoint.course);
|
||||
|
||||
@@ -207,13 +252,19 @@ public class VesselPathTracker {
|
||||
predictionPoints.add(predictionPoint);
|
||||
|
||||
try {
|
||||
Log.d(TAG, "Adding prediction line for vessel: " + vesselId);
|
||||
predictionLine = mapObjects.addPolyline(new com.yandex.mapkit.geometry.Polyline(predictionPoints));
|
||||
if (predictionLine != null) {
|
||||
predictionLine.setStrokeColor(predictionColor);
|
||||
predictionLine.setStrokeWidth(predictionWidth);
|
||||
// Сплошная линия для прогноза (по умолчанию)
|
||||
Log.d(TAG, "Prediction line created successfully for vessel: " + vesselId +
|
||||
", color: " + Integer.toHexString(predictionColor) +
|
||||
", width: " + predictionWidth);
|
||||
} else {
|
||||
Log.e(TAG, "Failed to create prediction line for vessel: " + vesselId);
|
||||
}
|
||||
} catch (RuntimeException ignored) {
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "Error creating prediction line for vessel: " + vesselId, e);
|
||||
isEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user