Files
falah-mobile/src/lib/qibla.ts
T
root 28be776c84 Add Prayer Reminder, Dhikr Counter, Qibla Finder, Halal Monitor updates
- Prayer reminder: /prayer page with 5 daily times, countdown, alAdhan API
- Dhikr counter: /dhikr page with 3 presets, custom counter, haptics, DB tracking
- Qibla finder: /qibla page with compass SVG, DeviceOrientation, bearing to Kaaba
- Halal Monitor: Leaflet + Google Places, 26 KL markers, geolocation, distance sort
- BottomNav: added clock icon for prayer
- Prisma: schema updates for DhikrSession, DhikrDay, DailyStreak, XpTransaction
- Geo utility module
- Weighted Traefik routing: Contabo 99% / Synology 1% cold standby
2026-06-18 14:51:07 +02:00

97 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Qibla direction calculation utilities.
*
* Computes the bearing (direction) from a user's location to the Kaaba in Mecca.
* Also provides distance to Mecca using the haversine formula.
*
* Kaaba coordinates: 21.4225° N, 39.8262° E
*/
const KAABA_LAT = 21.4225;
const KAABA_LNG = 39.8262;
/**
* Convert degrees to radians.
*/
function toRadians(deg: number): number {
return (deg * Math.PI) / 180;
}
/**
* Convert radians to degrees.
*/
function toDegrees(rad: number): number {
return (rad * 180) / Math.PI;
}
/**
* Calculate the bearing (direction) from a location to the Kaaba in Mecca.
*
* Uses the standard great-circle bearing formula:
* θ = atan2(sin(Δλ)·cos(φ₂), cos(φ₁)·sin(φ₂) sin(φ₁)·cos(φ₂)·cos(Δλ))
*
* @param lat User's latitude (degrees)
* @param lng User's longitude (degrees)
* @returns Bearing in degrees clockwise from North (0360)
*/
export function qiblaBearing(lat: number, lng: number): number {
const φ1 = toRadians(lat);
const φ2 = toRadians(KAABA_LAT);
const Δλ = toRadians(KAABA_LNG - lng);
const y = Math.sin(Δλ) * Math.cos(φ2);
const x =
Math.cos(φ1) * Math.sin(φ2) -
Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ);
let bearing = toDegrees(Math.atan2(y, x));
// Normalize to 0360
return (bearing + 360) % 360;
}
/**
* Calculate the distance from a location to the Kaaba in Mecca.
*
* @param lat User's latitude (degrees)
* @param lng User's longitude (degrees)
* @returns Distance in kilometres, rounded to 1 decimal place
*/
export function distanceToMecca(lat: number, lng: number): number {
const EARTH_RADIUS_KM = 6371;
const dLat = toRadians(KAABA_LAT - lat);
const dLng = toRadians(KAABA_LNG - lng);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRadians(lat)) *
Math.cos(toRadians(KAABA_LAT)) *
Math.sin(dLng / 2) ** 2;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return Math.round(EARTH_RADIUS_KM * c * 10) / 10;
}
/**
* Get a human-readable cardinal direction from a bearing.
*
* @param bearing Bearing in degrees (0360)
* @returns Cardinal direction string (e.g., "NE")
*/
export function bearingToDirection(bearing: number): string {
const dirs = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
const index = Math.round(bearing / 45) % 8;
return dirs[index];
}
/**
* Format distance in a human-readable way.
*/
export function formatDistance(km: number): string {
if (km < 1) return `${Math.round(km * 1000)} m`;
if (km < 100) return `${km.toFixed(1)} km`;
return `${Math.round(km).toLocaleString()} km`;
}
export { KAABA_LAT, KAABA_LNG };