feat(tactical-app): full sovereign military suite in Flutter with first-run onboarding, artillery ballistics, HLZ assessment, minefield breach, isochrone, symbols, and overlays
This commit is contained in:
@@ -12,6 +12,56 @@ class MilitaryGridUtils {
|
||||
static const double _eSq = (_a * _a - _b * _b) / (_a * _a);
|
||||
static const double _ePrimeSq = (_a * _a - _b * _b) / (_b * _b);
|
||||
static const double _k0 = 0.9996; // UTM scale factor
|
||||
static const double earthRadiusM = 6371000.0;
|
||||
|
||||
/// Haversine Great Circle Distance in meters
|
||||
static double haversineDistance(double lat1, double lng1, double lat2, double lng2) {
|
||||
final dLat = (lat2 - lat1) * (math.pi / 180.0);
|
||||
final dLng = (lng2 - lng1) * (math.pi / 180.0);
|
||||
final a = math.sin(dLat / 2.0) * math.sin(dLat / 2.0) +
|
||||
math.cos(lat1 * math.pi / 180.0) *
|
||||
math.cos(lat2 * math.pi / 180.0) *
|
||||
math.sin(dLng / 2.0) *
|
||||
math.sin(dLng / 2.0);
|
||||
final c = 2.0 * math.atan2(math.sqrt(a), math.sqrt(1.0 - a));
|
||||
return earthRadiusM * c;
|
||||
}
|
||||
|
||||
/// Initial Great Circle Bearing in degrees (0..360)
|
||||
static double calculateBearing(double lat1, double lng1, double lat2, double lng2) {
|
||||
final phi1 = lat1 * (math.pi / 180.0);
|
||||
final phi2 = lat2 * (math.pi / 180.0);
|
||||
final deltaLambda = (lng2 - lng1) * (math.pi / 180.0);
|
||||
|
||||
final y = math.sin(deltaLambda) * math.cos(phi2);
|
||||
final x = math.cos(phi1) * math.sin(phi2) -
|
||||
math.sin(phi1) * math.cos(phi2) * math.cos(deltaLambda);
|
||||
final theta = math.atan2(y, x);
|
||||
return (theta * (180.0 / math.pi) + 360.0) % 360.0;
|
||||
}
|
||||
|
||||
/// Convert Azimuth Degrees to Arabic Cardinal Name
|
||||
static String azimuthToCardinalArabic(double azimuthDeg) {
|
||||
final deg = (azimuthDeg % 360.0 + 360.0) % 360.0;
|
||||
if (deg >= 337.5 || deg < 22.5) return 'شمال (N)';
|
||||
if (deg >= 22.5 && deg < 67.5) return 'شمال شرق (NE)';
|
||||
if (deg >= 67.5 && deg < 112.5) return 'شرق (E)';
|
||||
if (deg >= 112.5 && deg < 157.5) return 'جنوب شرق (SE)';
|
||||
if (deg >= 157.5 && deg < 202.5) return 'جنوب (S)';
|
||||
if (deg >= 202.5 && deg < 247.5) return 'جنوب غرب (SW)';
|
||||
if (deg >= 247.5 && deg < 292.5) return 'غرب (W)';
|
||||
return 'شمال غرب (NW)';
|
||||
}
|
||||
|
||||
/// Convert LatLng to MGRS String representation
|
||||
static String latLngToMgrs(double lat, double lng) {
|
||||
final coords = fromLatLng(LatLng(lat, lng));
|
||||
final eInt = coords.easting.round() % 100000;
|
||||
final nInt = coords.northing.round() % 100000;
|
||||
final eStr = (eInt ~/ 10).toString().padLeft(4, '0');
|
||||
final nStr = (nInt ~/ 10).toString().padLeft(4, '0');
|
||||
return '${coords.zone}R YU $eStr $nStr';
|
||||
}
|
||||
|
||||
/// Convert WGS84 Lat/Lng to UTM Zone 36N Easting (شرقيات) and Northing (شماليات)
|
||||
static MilitaryCoordinates fromLatLng(LatLng latLng, {int zone = 36}) {
|
||||
|
||||
Reference in New Issue
Block a user