@chauffleet/expo-custom-map
Version:
Open source custom map library for Expo/React Native. Use your own tiles without Google Maps, Mapbox, or API keys. Created by ChaufFleet.
118 lines • 5.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.interpolateCoordinates = exports.normalizeCoordinate = exports.calculateTileBounds = exports.getBoundsZoom = exports.isPointInBounds = exports.getGeoBounds = exports.calculateBearing = exports.calculateDistance = exports.tileToLatLon = exports.latLonToTile = exports.rad2deg = exports.deg2rad = void 0;
// src/utils/geoUtils.ts
const deg2rad = (deg) => (deg * Math.PI) / 180;
exports.deg2rad = deg2rad;
const rad2deg = (rad) => (rad * 180) / Math.PI;
exports.rad2deg = rad2deg;
const latLonToTile = (lat, lon, zoom) => {
const x = Math.floor(((lon + 180) / 360) * Math.pow(2, zoom));
const y = Math.floor(((1 - Math.log(Math.tan((0, exports.deg2rad)(lat)) + 1 / Math.cos((0, exports.deg2rad)(lat))) / Math.PI) / 2) *
Math.pow(2, zoom));
return { x, y };
};
exports.latLonToTile = latLonToTile;
const tileToLatLon = (x, y, zoom) => {
const n = Math.pow(2, zoom);
const lon = (x / n) * 360 - 180;
const lat = (0, exports.rad2deg)(Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / n))));
return { lat, lon };
};
exports.tileToLatLon = tileToLatLon;
const calculateDistance = (coord1, coord2) => {
const R = 6371; // Earth radius in km
const dLat = (0, exports.deg2rad)(coord2[1] - coord1[1]);
const dLon = (0, exports.deg2rad)(coord2[0] - coord1[0]);
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((0, exports.deg2rad)(coord1[1])) * Math.cos((0, exports.deg2rad)(coord2[1])) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
};
exports.calculateDistance = calculateDistance;
const calculateBearing = (start, end) => {
const startLat = (0, exports.deg2rad)(start[1]);
const startLng = (0, exports.deg2rad)(start[0]);
const endLat = (0, exports.deg2rad)(end[1]);
const endLng = (0, exports.deg2rad)(end[0]);
const dLng = endLng - startLng;
const y = Math.sin(dLng) * Math.cos(endLat);
const x = Math.cos(startLat) * Math.sin(endLat) - Math.sin(startLat) * Math.cos(endLat) * Math.cos(dLng);
const bearing = (0, exports.rad2deg)(Math.atan2(y, x));
return (bearing + 360) % 360;
};
exports.calculateBearing = calculateBearing;
const getGeoBounds = (coordinates) => {
if (coordinates.length === 0) {
throw new Error('Cannot calculate bounds of empty coordinates array');
}
let north = coordinates[0][1];
let south = coordinates[0][1];
let east = coordinates[0][0];
let west = coordinates[0][0];
coordinates.forEach(([lon, lat]) => {
if (lat > north)
north = lat;
if (lat < south)
south = lat;
if (lon > east)
east = lon;
if (lon < west)
west = lon;
});
return { north, south, east, west };
};
exports.getGeoBounds = getGeoBounds;
const isPointInBounds = (point, bounds) => {
const [lon, lat] = point;
return lat <= bounds.north && lat >= bounds.south && lon <= bounds.east && lon >= bounds.west;
};
exports.isPointInBounds = isPointInBounds;
const getBoundsZoom = (bounds, screenWidth, screenHeight, tileSize = 256) => {
const latDiff = bounds.north - bounds.south;
const lonDiff = bounds.east - bounds.west;
const maxDiff = Math.max(latDiff, lonDiff);
const zoom = Math.floor(Math.log2(360 / maxDiff));
return Math.max(1, Math.min(18, zoom));
};
exports.getBoundsZoom = getBoundsZoom;
const calculateTileBounds = (lat, lon, radiusKm, zoom) => {
const latRad = (0, exports.deg2rad)(lat);
const degreeDistance = 111; // km par degré approximatif
const latDelta = radiusKm / degreeDistance;
const lonDelta = radiusKm / (degreeDistance * Math.cos(latRad));
const minLat = lat - latDelta;
const maxLat = lat + latDelta;
const minLon = lon - lonDelta;
const maxLon = lon + lonDelta;
const minTile = (0, exports.latLonToTile)(minLat, minLon, zoom);
const maxTile = (0, exports.latLonToTile)(maxLat, maxLon, zoom);
return {
minX: Math.min(minTile.x, maxTile.x),
maxX: Math.max(minTile.x, maxTile.x),
minY: Math.min(minTile.y, maxTile.y),
maxY: Math.max(minTile.y, maxTile.y),
};
};
exports.calculateTileBounds = calculateTileBounds;
const normalizeCoordinate = (coordinate) => {
let [lon, lat] = coordinate;
// Normaliser la longitude (-180 to 180)
lon = ((lon + 180) % 360) - 180;
// Clamp la latitude (-90 to 90)
lat = Math.max(-90, Math.min(90, lat));
return [lon, lat];
};
exports.normalizeCoordinate = normalizeCoordinate;
const interpolateCoordinates = (start, end, progress) => {
const startLon = start[0];
const startLat = start[1];
const endLon = end[0];
const endLat = end[1];
const lon = startLon + (endLon - startLon) * progress;
const lat = startLat + (endLat - startLat) * progress;
return [lon, lat];
};
exports.interpolateCoordinates = interpolateCoordinates;
//# sourceMappingURL=geoUtils.js.map