feat: major progress
This commit is contained in:
96
lib/util/geojson_util.dart
Normal file
96
lib/util/geojson_util.dart
Normal file
@ -0,0 +1,96 @@
|
||||
import 'package:geojson_vi/geojson_vi.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'dart:math';
|
||||
|
||||
void swapLatLonGeojsonGeometry(GeoJSONGeometry geometry) {
|
||||
if (geometry is GeoJSONPolygon) {
|
||||
geometry.coordinates[0] =
|
||||
geometry.coordinates[0].map((e) => [e[1], e[0]]).toList();
|
||||
} else if (geometry is GeoJSONPoint) {
|
||||
geometry.coordinates = [geometry.coordinates[1], geometry.coordinates[0]];
|
||||
} else {
|
||||
throw UnimplementedError(
|
||||
"Geometry of type ${geometry.runtimeType} point swapping is unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
List<double> latLonToGeoJSON(LatLng point) {
|
||||
return [point.longitude, point.latitude];
|
||||
}
|
||||
|
||||
LatLng geoJSONToLatLon(List<double> point) {
|
||||
return LatLng(point[1], point[0]);
|
||||
}
|
||||
|
||||
double degreesToRadians(double degrees) {
|
||||
return degrees * (pi / 180);
|
||||
}
|
||||
|
||||
double radiansToDegrees(double radians) {
|
||||
return radians * (180 / pi);
|
||||
}
|
||||
|
||||
double bearingBetweenLatLng(LatLng point1, LatLng point2) {
|
||||
return bearingBetween(
|
||||
point1.latitude,
|
||||
point1.longitude,
|
||||
point2.latitude,
|
||||
point2.longitude,
|
||||
);
|
||||
}
|
||||
|
||||
double bearingBetween(double lat1, double lon1, double lat2, double lon2) {
|
||||
var dLon = degreesToRadians(lon2 - lon1);
|
||||
var y = sin(dLon) * cos(degreesToRadians(lat2));
|
||||
var x = cos(degreesToRadians(lat1)) * sin(degreesToRadians(lat2)) -
|
||||
sin(degreesToRadians(lat1)) * cos(degreesToRadians(lat2)) * cos(dLon);
|
||||
var angle = atan2(y, x);
|
||||
return (radiansToDegrees(angle) + 360) % 360;
|
||||
}
|
||||
|
||||
double distanceBetweenLatLng(LatLng point1, LatLng point2, String unit) {
|
||||
return distanceBetween(point1.latitude, point1.longitude, point2.latitude,
|
||||
point2.longitude, unit);
|
||||
}
|
||||
|
||||
double distanceBetween(
|
||||
double lat1, double lon1, double lat2, double lon2, String unit) {
|
||||
const earthRadius = 6371; // in km
|
||||
// assuming earth is a perfect sphere(it's not)
|
||||
|
||||
// Convert degrees to radians
|
||||
final lat1Rad = degreesToRadians(lat1);
|
||||
final lon1Rad = degreesToRadians(lon1);
|
||||
final lat2Rad = degreesToRadians(lat2);
|
||||
final lon2Rad = degreesToRadians(lon2);
|
||||
|
||||
final dLat = lat2Rad - lat1Rad;
|
||||
final dLon = lon2Rad - lon1Rad;
|
||||
|
||||
// Haversine formula
|
||||
final a = pow(sin(dLat / 2), 2) +
|
||||
cos(lat1Rad) * cos(lat2Rad) * pow(sin(dLon / 2), 2);
|
||||
final c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||
|
||||
final distance = earthRadius * c;
|
||||
|
||||
return toRequestedUnit(unit, distance);
|
||||
|
||||
// return distance; // in km
|
||||
}
|
||||
|
||||
double toRequestedUnit(String unit, double distanceInKm) {
|
||||
switch (unit) {
|
||||
case 'kilometers':
|
||||
return distanceInKm;
|
||||
case 'meters':
|
||||
return distanceInKm * 1000;
|
||||
case 'miles':
|
||||
return (distanceInKm * 1000) / 1609.344;
|
||||
case 'yards':
|
||||
return distanceInKm * 1093.61;
|
||||
case '':
|
||||
return distanceInKm;
|
||||
}
|
||||
return distanceInKm;
|
||||
}
|
@ -35,3 +35,24 @@ LatLng polygonCenterAvg(List<LatLng> polygon) {
|
||||
|
||||
return LatLng(centerLat, centerLng);
|
||||
}
|
||||
|
||||
bool isPointInPolygonRaycast(LatLng point, List<LatLng> polygon) {
|
||||
bool inside = false;
|
||||
int len = polygon.length;
|
||||
|
||||
for (int i = 0, j = len - 1; i < len; j = i++) {
|
||||
LatLng pi = polygon[i];
|
||||
LatLng pj = polygon[j];
|
||||
|
||||
if (((pi.latitude > point.latitude) != (pj.latitude > point.latitude)) &&
|
||||
(point.longitude <
|
||||
(pj.longitude - pi.longitude) *
|
||||
(point.latitude - pi.latitude) /
|
||||
(pj.latitude - pi.latitude) +
|
||||
pi.longitude)) {
|
||||
inside = !inside;
|
||||
}
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
67
lib/util/util.dart
Normal file
67
lib/util/util.dart
Normal file
@ -0,0 +1,67 @@
|
||||
import 'package:uninav/data/geo/model.dart';
|
||||
|
||||
String formatDuration(Duration duration) {
|
||||
final days = duration.inDays;
|
||||
final hours = duration.inHours.remainder(24);
|
||||
final minutes = duration.inMinutes.remainder(60);
|
||||
final seconds = duration.inSeconds.remainder(60);
|
||||
|
||||
String plural(int thing) => thing == 1 ? '' : 's';
|
||||
|
||||
if (days > 0) {
|
||||
return '$days day${plural(days)}, $hours hour${plural(hours)}';
|
||||
} else if (hours > 0) {
|
||||
return '$hours hour${plural(hours)}, $minutes minute${plural(minutes)}';
|
||||
} else if (minutes > 0) {
|
||||
return '$minutes minute${plural(minutes)}, $seconds second${plural(seconds)}';
|
||||
} else {
|
||||
return '$seconds second${plural(seconds)}';
|
||||
}
|
||||
}
|
||||
|
||||
String formatFeatureTitle(Feature feature) {
|
||||
return feature.type.when(
|
||||
building: () => '${feature.name} (Building)',
|
||||
lectureHall: () => '${feature.name} (Lecture Hall)',
|
||||
room: () => 'Room ${feature.name}',
|
||||
door: (_) => 'Door',
|
||||
toilet: (type) => 'Toilet (${formatToiletType(feature.type as Toilet)})',
|
||||
stairs: (_) => 'Stairs',
|
||||
lift: (_) => 'Lift',
|
||||
publicTransport: (_, __) => 'Public Transport',
|
||||
);
|
||||
}
|
||||
|
||||
String formatToiletType(Toilet toilet) {
|
||||
final type = toilet.toilet_type.toLowerCase();
|
||||
switch (type) {
|
||||
case 'male':
|
||||
return 'Male';
|
||||
case 'female':
|
||||
return 'Female';
|
||||
case 'handicap':
|
||||
return 'Handicap';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
String formatDistance(int distanceInMeters) {
|
||||
if (distanceInMeters < 1000) {
|
||||
// If the distance is less than 1 kilometer, display it in meters.
|
||||
return '${distanceInMeters}m';
|
||||
} else {
|
||||
// If the distance is 1 kilometer or more, display it in kilometers and meters.
|
||||
final kilometers =
|
||||
distanceInMeters ~/ 1000; // Integer division to get whole kilometers.
|
||||
final meters =
|
||||
distanceInMeters % 1000; // Remainder to get the remaining meters.
|
||||
if (meters == 0) {
|
||||
// If there are no remaining meters, display only kilometers.
|
||||
return '${kilometers}km';
|
||||
} else {
|
||||
// If there are remaining meters, display both kilometers and meters.
|
||||
return '${kilometers}km ${meters}m';
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user