qibla/.github/wiki/guides/advanced.md

3.1 KiB

Advanced Usage

Compass overlay integration

The eight-point compass abbreviation is suited for UI labels. Map the bearing to a rotation for a needle overlay:

import { qiblaAngle } from '@acamarata/qibla';

const bearing = qiblaAngle(lat, lng);

// CSS rotation for a compass needle pointing north by default
const rotation = `rotate(${bearing}deg)`;
needle.style.transform = rotation;

The bearing is clockwise from true north, matching CSS rotate() semantics directly.

Dense great-circle paths

Pass a higher step count for smoother polylines on a map:

import { qiblaGreatCircle, KAABA_LAT, KAABA_LNG } from '@acamarata/qibla';

const observer = [40.7128, -74.0060]; // New York
const steps    = 100;

const path = qiblaGreatCircle(observer[0], observer[1], steps);

// Flatten for Leaflet / Google Maps / Mapbox polyline
const latLngs = path.map(([lat, lng]) => ({ lat, lng }));

The default step count is 20. Steps above 200 are rarely useful for display.

Magnetic vs true north

qiblaAngle returns bearing relative to true north. For a physical compass, apply the local magnetic declination:

import { qiblaAngle } from '@acamarata/qibla';

const trueBearing = qiblaAngle(lat, lng);

// Magnetic declination for New York (west = negative)
const declination = -13.2;

const magneticBearing = (trueBearing - declination + 360) % 360;
console.log(`Magnetic: ${magneticBearing.toFixed(1)}°`);

Magnetic declination varies by location and year. Use a current value from NOAA's World Magnetic Model or a service like @mapbox/geodeticsurvey.

Polar and edge cases

Observers at the poles have undefined bearing — the great circle is ambiguous. qiblaAngle returns NaN for latitudes exactly at ±90. Check before using:

const bearing = qiblaAngle(90, 0); // NaN — north pole
if (!isFinite(bearing)) {
  console.log('Bearing undefined at this location.');
}

Observers very close to Mecca (within ~1 km) may get erratic bearings due to floating-point precision near the target. No special handling is needed in practice.

Batch calculation for multiple cities

import { qiblaAngle, compassDir, distanceKm, KAABA_LAT, KAABA_LNG } from '@acamarata/qibla';

const cities = [
  { name: 'New York',     lat:  40.7128, lng:  -74.0060 },
  { name: 'London',       lat:  51.5074, lng:   -0.1278 },
  { name: 'Istanbul',     lat:  41.0082, lng:   28.9784 },
  { name: 'Kuala Lumpur', lat:   3.1390, lng:  101.6869 },
  { name: 'Sydney',       lat: -33.8688, lng:  151.2093 },
];

console.log('City'.padEnd(16) + 'Bearing  Dir   Distance');
console.log('-'.repeat(46));

for (const c of cities) {
  const b   = qiblaAngle(c.lat, c.lng);
  const dir = compassDir(b);
  const km  = distanceKm(c.lat, c.lng, KAABA_LAT, KAABA_LNG);
  console.log(
    c.name.padEnd(16) +
    `${b.toFixed(1).padStart(6)}°  ${dir.padEnd(4)}  ${Math.round(km).toLocaleString()} km`
  );
}
  • API Reference — parameter types, return values, thrown errors
  • Architecture — algorithm details, coordinate system, Ka'bah coordinates