first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import '../models/gps_coordinate.dart';
|
||||
|
||||
/// أداة ترميز وفك ترميز Polyline
|
||||
/// تستخدم خوارزمية Google Encoded Polyline لضغط المسارات بنسبة ~95%
|
||||
class PolylineUtility {
|
||||
/// Encode a list of GPS coordinates to a polyline string
|
||||
static String encode(List<GpsCoordinate> coordinates) {
|
||||
if (coordinates.isEmpty) return '';
|
||||
|
||||
final buffer = StringBuffer();
|
||||
int prevLat = 0;
|
||||
int prevLng = 0;
|
||||
|
||||
for (final point in coordinates) {
|
||||
int lat = (point.latitude * 1e5).round();
|
||||
int lng = (point.longitude * 1e5).round();
|
||||
|
||||
_encodeValue(lat - prevLat, buffer);
|
||||
_encodeValue(lng - prevLng, buffer);
|
||||
|
||||
prevLat = lat;
|
||||
prevLng = lng;
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Decode a polyline string back to coordinates
|
||||
static List<GpsCoordinate> decode(String encoded) {
|
||||
if (encoded.isEmpty) return [];
|
||||
|
||||
final coordinates = <GpsCoordinate>[];
|
||||
int index = 0;
|
||||
int lat = 0;
|
||||
int lng = 0;
|
||||
|
||||
while (index < encoded.length) {
|
||||
lat += _decodeValue(encoded, index);
|
||||
index = _lastIndex;
|
||||
|
||||
if (index >= encoded.length) break;
|
||||
|
||||
lng += _decodeValue(encoded, index);
|
||||
index = _lastIndex;
|
||||
|
||||
coordinates.add(GpsCoordinate(
|
||||
latitude: lat / 1e5,
|
||||
longitude: lng / 1e5,
|
||||
timestamp: DateTime.now(), // Polylines don't store timestamps
|
||||
));
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
// Internal tracking for decode position
|
||||
static int _lastIndex = 0;
|
||||
|
||||
static void _encodeValue(int value, StringBuffer buffer) {
|
||||
int v = value < 0 ? ~(value << 1) : (value << 1);
|
||||
while (v >= 0x20) {
|
||||
buffer.writeCharCode((0x20 | (v & 0x1f)) + 63);
|
||||
v >>= 5;
|
||||
}
|
||||
buffer.writeCharCode(v + 63);
|
||||
}
|
||||
|
||||
static int _decodeValue(String encoded, int startIndex) {
|
||||
int result = 0;
|
||||
int shift = 0;
|
||||
int index = startIndex;
|
||||
|
||||
while (index < encoded.length) {
|
||||
int byte = encoded.codeUnitAt(index) - 63;
|
||||
index++;
|
||||
result |= (byte & 0x1f) << shift;
|
||||
shift += 5;
|
||||
if (byte < 0x20) break;
|
||||
}
|
||||
|
||||
_lastIndex = index;
|
||||
return (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user