fix(tactical): implement dynamic MGRS grid conversion, triangle of error resection accuracy, clean surveyed IDW elevation, and robust offline sync validation
This commit is contained in:
@@ -53,14 +53,97 @@ class MilitaryGridUtils {
|
||||
return 'شمال غرب (NW)';
|
||||
}
|
||||
|
||||
/// Convert LatLng to MGRS String representation
|
||||
static String latLngToMgrs(double lat, double lng) {
|
||||
final coords = fromLatLng(LatLng(lat, lng));
|
||||
/// Convert LatLng to standard MGRS String representation (Zone + Band + 100k Square ID + Easting/Northing)
|
||||
static String latLngToMgrs(double lat, double lng, {int accuracyDigits = 4}) {
|
||||
if (lat < -80.0 || lat > 84.0) {
|
||||
return 'OUT_OF_BOUNDS';
|
||||
}
|
||||
|
||||
final zone = ((lng + 180.0) / 6.0).floor() + 1;
|
||||
final coords = fromLatLng(LatLng(lat, lng), zone: zone);
|
||||
|
||||
final bandLetter = _getLatitudeBandLetter(lat);
|
||||
final squareId = _get100kSquareId(coords.easting, coords.northing, zone);
|
||||
|
||||
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';
|
||||
|
||||
// Pad to 5 digits then trim to desired accuracy
|
||||
final e5 = eInt.toString().padLeft(5, '0');
|
||||
final n5 = nInt.toString().padLeft(5, '0');
|
||||
|
||||
final eStr = e5.substring(0, math.min(5, accuracyDigits));
|
||||
final nStr = n5.substring(0, math.min(5, accuracyDigits));
|
||||
|
||||
return '$zone$bandLetter $squareId $eStr $nStr';
|
||||
}
|
||||
|
||||
/// Latitude band letter (8-degree bands from -80° to +84°: C to X, skipping I and O)
|
||||
static String _getLatitudeBandLetter(double lat) {
|
||||
const bands = 'CDEFGHJKLMNPQRSTUVWX';
|
||||
if (lat >= 84.0) return 'X';
|
||||
if (lat < -80.0) return 'C';
|
||||
int index = ((lat + 80.0) / 8.0).floor();
|
||||
if (index < 0) index = 0;
|
||||
if (index >= bands.length) index = bands.length - 1;
|
||||
return bands[index];
|
||||
}
|
||||
|
||||
/// 100,000-meter Square Identification (2 letters) per US DMA TM 8358.1 / WGS84 standard
|
||||
static String _get100kSquareId(double easting, double northing, int zone) {
|
||||
const setColOrigin = 'AJSAJS';
|
||||
const setRowOrigin = 'AFAFAF';
|
||||
const aCode = 65; // 'A'
|
||||
const iCode = 73; // 'I'
|
||||
const oCode = 79; // 'O'
|
||||
const vCode = 86; // 'V'
|
||||
const zCode = 90; // 'Z'
|
||||
|
||||
final setParm = (zone % 6 == 0) ? 6 : (zone % 6);
|
||||
final setIndex = setParm - 1;
|
||||
|
||||
final colOrigin = setColOrigin.codeUnitAt(setIndex);
|
||||
final rowOrigin = setRowOrigin.codeUnitAt(setIndex);
|
||||
|
||||
final col = (easting / 100000.0).floor();
|
||||
final row = (northing / 100000.0).floor() % 20;
|
||||
|
||||
var colInt = colOrigin + col - 1;
|
||||
var rowInt = rowOrigin + row;
|
||||
var colRollover = false;
|
||||
|
||||
if (colInt > zCode) {
|
||||
colInt = colInt - zCode + aCode - 1;
|
||||
colRollover = true;
|
||||
}
|
||||
if (colInt == iCode || (colOrigin < iCode && colInt > iCode) || ((colInt > iCode || colOrigin < iCode) && colRollover)) {
|
||||
colInt++;
|
||||
}
|
||||
if (colInt == oCode || (colOrigin < oCode && colInt > oCode) || ((colInt > oCode || colOrigin < oCode) && colRollover)) {
|
||||
colInt++;
|
||||
if (colInt == iCode) colInt++;
|
||||
}
|
||||
if (colInt > zCode) {
|
||||
colInt = colInt - zCode + aCode - 1;
|
||||
}
|
||||
|
||||
var rowRollover = false;
|
||||
if (rowInt > vCode) {
|
||||
rowInt = rowInt - vCode + aCode - 1;
|
||||
rowRollover = true;
|
||||
}
|
||||
if (rowInt == iCode || (rowOrigin < iCode && rowInt > iCode) || ((rowInt > iCode || rowOrigin < iCode) && rowRollover)) {
|
||||
rowInt++;
|
||||
}
|
||||
if (rowInt == oCode || (rowOrigin < oCode && rowInt > oCode) || ((rowInt > oCode || rowOrigin < oCode) && rowRollover)) {
|
||||
rowInt++;
|
||||
if (rowInt == iCode) rowInt++;
|
||||
}
|
||||
if (rowInt > vCode) {
|
||||
rowInt = rowInt - vCode + aCode - 1;
|
||||
}
|
||||
|
||||
return String.fromCharCode(colInt) + String.fromCharCode(rowInt);
|
||||
}
|
||||
|
||||
/// Convert WGS84 Lat/Lng to UTM Zone 36N Easting (شرقيات) and Northing (شماليات)
|
||||
|
||||
Reference in New Issue
Block a user