UNPKG

houser-js-utils

Version:

A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.

380 lines (379 loc) 14.4 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const LocationUtils = { /** * Calculates the bearing (direction) between two geographic coordinates using the Haversine formula. * @param lat1 - The first latitude in degrees * @param lon1 - The first longitude in degrees * @param lat2 - The second latitude in degrees * @param lon2 - The second longitude in degrees * @returns The bearing in degrees (0-360) from north * @example * ```typescript * // Calculate bearing from New York to London * const bearing = LocationUtils.calculateBearing(40.7128, -74.0060, 51.5074, -0.1278); * console.log(`Bearing: ${bearing.toFixed(1)}°`); // "Bearing: 77.5°" * * // Calculate bearing between two points in the same city * const localBearing = LocationUtils.calculateBearing(40.7128, -74.0060, 40.7589, -73.9851); * console.log(`Local bearing: ${localBearing.toFixed(1)}°`); // "Local bearing: 45.2°" * ``` */ calculateBearing(lat1, lon1, lat2, lon2) { const dLon = this.toRad(lon2 - lon1); const lat1Rad = this.toRad(lat1); const lat2Rad = this.toRad(lat2); const y = Math.sin(dLon) * Math.cos(lat2Rad); const x = Math.cos(lat1Rad) * Math.sin(lat2Rad) - Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(dLon); let bearing = this.toDeg(Math.atan2(y, x)); bearing = (bearing + 360) % 360; return bearing; }, /** * Calculates a new coordinate point based on a starting point, distance, and bearing using the Haversine formula. * @param lat - The starting latitude in degrees * @param lon - The starting longitude in degrees * @param distance - The distance to travel in kilometers * @param bearing - The bearing (direction) in degrees (0-360) * @returns An object containing the new latitude and longitude coordinates * @example * ```typescript * // Calculate a point 100km northeast of New York * const destination = LocationUtils.calculateDestination(40.7128, -74.0060, 100, 45); * console.log(`Destination: ${destination.latitude.toFixed(4)}, ${destination.longitude.toFixed(4)}`); * // "Destination: 41.4000, -73.1000" * * // Calculate a point 50km south of a location * const southPoint = LocationUtils.calculateDestination(40.7128, -74.0060, 50, 180); * console.log(`South point: ${southPoint.latitude.toFixed(4)}, ${southPoint.longitude.toFixed(4)}`); * ``` */ calculateDestination(lat, lon, distance, bearing) { const R = 6371; const d = distance / R; const lat1 = this.toRad(lat); const lon1 = this.toRad(lon); const brng = this.toRad(bearing); const lat2 = Math.asin( Math.sin(lat1) * Math.cos(d) + Math.cos(lat1) * Math.sin(d) * Math.cos(brng) ); const lon2 = lon1 + Math.atan2( Math.sin(brng) * Math.sin(d) * Math.cos(lat1), Math.cos(d) - Math.sin(lat1) * Math.sin(lat2) ); return { latitude: this.toDeg(lat2), longitude: this.toDeg(lon2) }; }, /** * Calculates the great-circle distance between two geographic coordinates using the Haversine formula. * @param lat1 - The first latitude in degrees * @param lon1 - The first longitude in degrees * @param lat2 - The second latitude in degrees * @param lon2 - The second longitude in degrees * @returns The distance in kilometers * @example * ```typescript * // Calculate distance between New York and London * const distance = LocationUtils.calculateDistance(40.7128, -74.0060, 51.5074, -0.1278); * console.log(`Distance: ${distance.toFixed(1)} km`); // "Distance: 5570.2 km" * * // Calculate distance between two points in the same city * const localDistance = LocationUtils.calculateDistance(40.7128, -74.0060, 40.7589, -73.9851); * console.log(`Local distance: ${localDistance.toFixed(2)} km`); // "Local distance: 8.45 km" * ``` */ calculateDistance(lat1, lon1, lat2, lon2) { const R = 6371; const dLat = this.toRad(lat2 - lat1); const dLon = this.toRad(lon2 - lon1); const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.toRad(lat1)) * Math.cos(this.toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; }, /** * Stops watching the user's position that was previously started with watchPosition. * @param watchId - The watch ID returned by watchPosition * @throws {Error} If geolocation is not supported by the browser * @example * ```typescript * // Start watching position * const watchId = LocationUtils.watchPosition(position => { * console.log('Position updated:', position.coords); * }); * * // Later, stop watching * LocationUtils.clearWatch(watchId); * console.log('Position watching stopped'); * ``` */ clearWatch(watchId) { if (!navigator.geolocation) { throw new Error("Geolocation is not supported by your browser"); } navigator.geolocation.clearWatch(watchId); }, /** * Formats geographic coordinates as a string in either decimal degrees (DD) or degrees, minutes, seconds (DMS) format. * @param lat - The latitude in degrees * @param lon - The longitude in degrees * @param format - The format to use: 'DD' for decimal degrees or 'DMS' for degrees, minutes, seconds * @returns A formatted coordinate string * @example * ```typescript * // Decimal degrees format * const dd = LocationUtils.formatCoordinate(40.7128, -74.0060, 'DD'); * console.log(dd); // "40.712800, -74.006000" * * // Degrees, minutes, seconds format * const dms = LocationUtils.formatCoordinate(40.7128, -74.0060, 'DMS'); * console.log(dms); // "40° 42' 46.08" N, 74° 0' 21.60" W" * * // Southern hemisphere example * const sydney = LocationUtils.formatCoordinate(-33.8688, 151.2093, 'DMS'); * console.log(sydney); // "33° 52' 7.68" S, 151° 12' 33.48" E" * ``` */ formatCoordinate(lat, lon, format = "DD") { if (format === "DD") { return `${lat.toFixed(6)}, ${lon.toFixed(6)}`; } const latDir = lat >= 0 ? "N" : "S"; const lonDir = lon >= 0 ? "E" : "W"; const latAbs = Math.abs(lat); const lonAbs = Math.abs(lon); const latDeg = Math.floor(latAbs); const latMin = Math.floor((latAbs - latDeg) * 60); const latSec = ((latAbs - latDeg) * 60 - latMin) * 60; const lonDeg = Math.floor(lonAbs); const lonMin = Math.floor((lonAbs - lonDeg) * 60); const lonSec = ((lonAbs - lonDeg) * 60 - lonMin) * 60; return `${latDeg}° ${latMin}' ${latSec.toFixed( 2 )}" ${latDir}, ${lonDeg}° ${lonMin}' ${lonSec.toFixed(2)}" ${lonDir}`; }, /** * Gets the user's current position using the browser's Geolocation API. * @param options - Geolocation options for accuracy, timeout, and maximum age * @returns A Promise that resolves with the GeolocationPosition object * @throws {Error} If geolocation is not supported by the browser * @example * ```typescript * try { * const position = await LocationUtils.getCurrentPosition({ * enableHighAccuracy: true, * timeout: 5000, * maximumAge: 0 * }); * * console.log(`Latitude: ${position.coords.latitude}`); * console.log(`Longitude: ${position.coords.longitude}`); * console.log(`Accuracy: ${position.coords.accuracy} meters`); * } catch (error) { * console.error('Error getting position:', error); * } * ``` */ async getCurrentPosition(options = { enableHighAccuracy: true, timeout: 5e3, maximumAge: 0 }) { return new Promise((resolve, reject) => { if (!navigator.geolocation) { reject(new Error("Geolocation is not supported by your browser")); return; } navigator.geolocation.getCurrentPosition(resolve, reject, options); }); }, /** * Calculates the center point of a geographic bounding box. * @param bounds - The bounding box with north, south, east, and west coordinates * @returns An object containing the latitude and longitude of the center point * @example * ```typescript * const bounds = { * north: 41.0, * south: 40.0, * east: -73.0, * west: -74.0 * }; * * const center = LocationUtils.getBoundsCenter(bounds); * console.log(`Center: ${center.latitude.toFixed(4)}, ${center.longitude.toFixed(4)}`); * // "Center: 40.5000, -73.5000" * ``` */ getBoundsCenter(bounds) { return { latitude: (bounds.north + bounds.south) / 2, longitude: (bounds.east + bounds.west) / 2 }; }, /** * Calculates a bounding box for a given radius around a center point. * @param lat - The center latitude in degrees * @param lon - The center longitude in degrees * @param radius - The radius in kilometers * @returns A bounding box with north, south, east, and west coordinates * @example * ```typescript * // Get bounding box for 10km radius around New York * const bounds = LocationUtils.getBoundsForRadius(40.7128, -74.0060, 10); * console.log('Bounding box:', bounds); * // { * // north: 40.8028, * // south: 40.6228, * // east: -73.9060, * // west: -74.1060 * // } * * // Check if a point is within this radius * const isInside = LocationUtils.isWithinBounds(40.7589, -73.9851, bounds); * console.log(`Point is within 10km: ${isInside}`); // true * ``` */ getBoundsForRadius(lat, lon, radius) { const R = 6371; const latRad = this.toRad(lat); const lonRad = this.toRad(lon); const d = radius / R; const north = this.toDeg(latRad + d); const south = this.toDeg(latRad - d); const east = this.toDeg(lonRad + d / Math.cos(latRad)); const west = this.toDeg(lonRad - d / Math.cos(latRad)); return { north, south, east, west }; }, /** * Checks if a coordinate point is within a geographic bounding box. * @param lat - The latitude to check in degrees * @param lon - The longitude to check in degrees * @param bounds - The bounding box with north, south, east, and west coordinates * @returns True if the coordinate is within the bounds, false otherwise * @example * ```typescript * const bounds = { * north: 41.0, * south: 40.0, * east: -73.0, * west: -75.0 * }; * * // Check if New York is within bounds * const isInside = LocationUtils.isWithinBounds(40.7128, -74.0060, bounds); * console.log(`New York is within bounds: ${isInside}`); // true * * // Check if London is within bounds * const isLondonInside = LocationUtils.isWithinBounds(51.5074, -0.1278, bounds); * console.log(`London is within bounds: ${isLondonInside}`); // false * ``` */ isWithinBounds(lat, lon, bounds) { return lat <= bounds.north && lat >= bounds.south && lon <= bounds.east && lon >= bounds.west; }, /** * Parses a coordinate string in decimal degrees format into latitude and longitude values. * @param coordinate - The coordinate string in "latitude, longitude" format * @returns An object containing the parsed latitude and longitude * @throws {Error} If the coordinate string is invalid or cannot be parsed * @example * ```typescript * // Parse a coordinate string * const coord = LocationUtils.parseCoordinate("40.7128, -74.0060"); * console.log(`Latitude: ${coord.latitude}, Longitude: ${coord.longitude}`); * // "Latitude: 40.7128, Longitude: -74.0060" * * try { * // Invalid format * const invalid = LocationUtils.parseCoordinate("invalid"); * } catch (error) { * console.error('Error:', error.message); // "Invalid coordinate format" * } * ``` */ parseCoordinate(coordinate) { const parts = coordinate.split(",").map((part) => part.trim()); if (parts.length !== 2) { throw new Error("Invalid coordinate format"); } const lat = parseFloat(parts[0]); const lon = parseFloat(parts[1]); if (isNaN(lat) || isNaN(lon)) { throw new Error("Invalid coordinate values"); } return { latitude: lat, longitude: lon }; }, /** * Converts an angle from radians to degrees. * @param radians - The angle in radians * @returns The angle in degrees * @example * ```typescript * const degrees = LocationUtils.toDeg(Math.PI); * console.log(`${degrees}°`); // "180°" * * const halfCircle = LocationUtils.toDeg(Math.PI / 2); * console.log(`${halfCircle}°`); // "90°" * ``` */ toDeg(radians) { return radians * 180 / Math.PI; }, /** * Converts an angle from degrees to radians. * @param degrees - The angle in degrees * @returns The angle in radians * @example * ```typescript * const radians = LocationUtils.toRad(180); * console.log(radians); // 3.141592653589793 (Math.PI) * * const halfCircle = LocationUtils.toRad(90); * console.log(halfCircle); // 1.5707963267948966 (Math.PI / 2) * ``` */ toRad(degrees) { return degrees * Math.PI / 180; }, /** * Starts watching the user's position using the browser's Geolocation API. * @param callback - The callback function to be called with position updates * @param options - Geolocation options for accuracy, timeout, and maximum age * @returns A watch ID that can be used to stop watching with clearWatch * @throws {Error} If geolocation is not supported by the browser * @example * ```typescript * // Start watching position with high accuracy * const watchId = LocationUtils.watchPosition( * position => { * console.log('Position updated:'); * console.log(`Latitude: ${position.coords.latitude}`); * console.log(`Longitude: ${position.coords.longitude}`); * console.log(`Accuracy: ${position.coords.accuracy} meters`); * }, * { * enableHighAccuracy: true, * timeout: 5000, * maximumAge: 0 * } * ); * * // Later, stop watching * LocationUtils.clearWatch(watchId); * ``` */ watchPosition(callback, options = { enableHighAccuracy: true, timeout: 5e3, maximumAge: 0 }) { if (!navigator.geolocation) { throw new Error("Geolocation is not supported by your browser"); } return navigator.geolocation.watchPosition(callback, void 0, options); } }; exports.LocationUtils = LocationUtils; //# sourceMappingURL=LocationUtils.js.map