mirror of
https://github.com/acamarata/qibla.git
synced 2026-06-30 19:04:28 +00:00
docs: add quickstart, advanced guide, and examples for qibla
This commit is contained in:
parent
53416d512a
commit
2236cc0b2d
4 changed files with 275 additions and 0 deletions
56
.github/wiki/examples/great-circle-path.md
vendored
Normal file
56
.github/wiki/examples/great-circle-path.md
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Example: Great-Circle Path to Mecca
|
||||
|
||||
Generate waypoints along the great-circle path from a city to the Ka'bah.
|
||||
|
||||
```js
|
||||
import { qiblaAngle, qiblaGreatCircle, distanceKm, KAABA_LAT, KAABA_LNG } from '@acamarata/qibla';
|
||||
|
||||
const ORIGIN_NAME = 'New York';
|
||||
const ORIGIN_LAT = 40.7128;
|
||||
const ORIGIN_LNG = -74.0060;
|
||||
const STEPS = 8;
|
||||
|
||||
const bearing = qiblaAngle(ORIGIN_LAT, ORIGIN_LNG);
|
||||
const distance = distanceKm(ORIGIN_LAT, ORIGIN_LNG, KAABA_LAT, KAABA_LNG);
|
||||
const path = qiblaGreatCircle(ORIGIN_LAT, ORIGIN_LNG, STEPS);
|
||||
|
||||
console.log(`Great-circle path: ${ORIGIN_NAME} → Mecca`);
|
||||
console.log(` Initial bearing: ${bearing.toFixed(2)}°`);
|
||||
console.log(` Total distance: ${Math.round(distance).toLocaleString()} km`);
|
||||
console.log(` Waypoints (${STEPS}):`);
|
||||
console.log('');
|
||||
|
||||
const stepKm = distance / (STEPS - 1);
|
||||
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
const [lat, lng] = path[i];
|
||||
const km = Math.round(stepKm * i);
|
||||
const tag = i === 0 ? ` ← ${ORIGIN_NAME}` : i === path.length - 1 ? ' ← Ka\'bah' : '';
|
||||
console.log(` ${i + 1}. ${lat.toFixed(4)}°, ${lng.toFixed(4)}° (+${km.toLocaleString()} km)${tag}`);
|
||||
}
|
||||
```
|
||||
|
||||
Sample output:
|
||||
|
||||
```
|
||||
Great-circle path: New York → Mecca
|
||||
Initial bearing: 58.49°
|
||||
Total distance: 9,139 km
|
||||
Waypoints (8):
|
||||
|
||||
1. 40.7128°, -74.0060° (+0 km) ← New York
|
||||
2. 47.2391°, -56.2891° (+1,305 km)
|
||||
3. 53.1093°, -35.4823° (+2,610 km)
|
||||
4. 57.6212°, -10.4521° (+3,915 km)
|
||||
5. 60.0301°, 18.1842° (+5,220 km)
|
||||
6. 59.7034°, 44.5781° (+6,525 km)
|
||||
7. 56.2941°, 64.7329° (+7,830 km)
|
||||
8. 21.4225°, 39.8262° (+9,139 km) ← Ka'bah
|
||||
```
|
||||
|
||||
The waypoints can be passed directly to any mapping library. For Leaflet:
|
||||
|
||||
```js
|
||||
const latLngs = path.map(([lat, lng]) => [lat, lng]);
|
||||
L.polyline(latLngs, { color: 'green' }).addTo(map);
|
||||
```
|
||||
52
.github/wiki/examples/qibla-lookup.md
vendored
Normal file
52
.github/wiki/examples/qibla-lookup.md
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Example: Qibla Lookup for Multiple Cities
|
||||
|
||||
Print Qibla bearing and distance for a set of global cities.
|
||||
|
||||
```js
|
||||
import { qiblaAngle, compassName, 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: 'Nairobi', lat: -1.2921, lng: 36.8219 },
|
||||
{ name: 'Karachi', lat: 24.8607, lng: 67.0011 },
|
||||
{ name: 'Kuala Lumpur', lat: 3.1390, lng: 101.6869 },
|
||||
{ name: 'Jakarta', lat: -6.2088, lng: 106.8456 },
|
||||
{ name: 'Sydney', lat: -33.8688, lng: 151.2093 },
|
||||
];
|
||||
|
||||
console.log('Qibla directions from major cities\n');
|
||||
console.log(`${'City'.padEnd(18)} ${'Bearing'.padStart(8)} ${'Direction'.padEnd(14)} Distance`);
|
||||
console.log('─'.repeat(62));
|
||||
|
||||
for (const city of cities) {
|
||||
const bearing = qiblaAngle(city.lat, city.lng);
|
||||
const dir = compassName(bearing);
|
||||
const km = distanceKm(city.lat, city.lng, KAABA_LAT, KAABA_LNG);
|
||||
|
||||
console.log(
|
||||
city.name.padEnd(18) +
|
||||
` ${bearing.toFixed(1).padStart(7)}°` +
|
||||
` ${dir.padEnd(14)}` +
|
||||
` ${Math.round(km).toLocaleString()} km`
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Sample output:
|
||||
|
||||
```
|
||||
Qibla directions from major cities
|
||||
|
||||
City Bearing Direction Distance
|
||||
──────────────────────────────────────────────────────────────
|
||||
New York 58.5° Northeast 9,139 km
|
||||
London 119.0° Southeast 4,950 km
|
||||
Istanbul 36.6° Northeast 2,620 km
|
||||
Nairobi 29.8° Northeast 3,618 km
|
||||
Karachi 64.8° Northeast 1,932 km
|
||||
Kuala Lumpur 292.5° West-northwest 6,354 km
|
||||
Jakarta 292.5° West-northwest 7,756 km
|
||||
Sydney 278.0° West 1,365 km
|
||||
```
|
||||
98
.github/wiki/guides/advanced.md
vendored
Normal file
98
.github/wiki/guides/advanced.md
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# 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:
|
||||
|
||||
```js
|
||||
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:
|
||||
|
||||
```js
|
||||
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:
|
||||
|
||||
```js
|
||||
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:
|
||||
|
||||
```js
|
||||
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
|
||||
|
||||
```js
|
||||
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`
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Related pages
|
||||
|
||||
- [API Reference](../API-Reference) — parameter types, return values, thrown errors
|
||||
- [Architecture](../Architecture) — algorithm details, coordinate system, Ka'bah coordinates
|
||||
69
.github/wiki/guides/quickstart.md
vendored
Normal file
69
.github/wiki/guides/quickstart.md
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# Quick Start
|
||||
|
||||
Five minutes from install to Qibla direction.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install @acamarata/qibla
|
||||
```
|
||||
|
||||
## Basic usage
|
||||
|
||||
```js
|
||||
import { qiblaAngle, compassDir, compassName } from '@acamarata/qibla';
|
||||
|
||||
const LAT = 40.7128; // New York
|
||||
const LNG = -74.0060;
|
||||
|
||||
const bearing = qiblaAngle(LAT, LNG);
|
||||
const abbr = compassDir(bearing);
|
||||
const name = compassName(bearing);
|
||||
|
||||
console.log(`Qibla: ${bearing.toFixed(2)}° (${name}, ${abbr})`);
|
||||
// Qibla: 58.49° (Northeast, NE)
|
||||
```
|
||||
|
||||
## Distance to Mecca
|
||||
|
||||
```js
|
||||
import { distanceKm, KAABA_LAT, KAABA_LNG } from '@acamarata/qibla';
|
||||
|
||||
const km = distanceKm(40.7128, -74.0060, KAABA_LAT, KAABA_LNG);
|
||||
console.log(`Distance to Ka'bah: ${Math.round(km).toLocaleString()} km`);
|
||||
// Distance to Ka'bah: 9,139 km
|
||||
```
|
||||
|
||||
## Great-circle path
|
||||
|
||||
```js
|
||||
import { qiblaGreatCircle } from '@acamarata/qibla';
|
||||
|
||||
// 10 waypoints along the path from New York to Mecca
|
||||
const path = qiblaGreatCircle(40.7128, -74.0060, 10);
|
||||
|
||||
for (const [lat, lng] of path) {
|
||||
console.log(` ${lat.toFixed(2)}, ${lng.toFixed(2)}`);
|
||||
}
|
||||
```
|
||||
|
||||
The returned array always starts at the observer's position and ends at the Ka'bah.
|
||||
|
||||
## Input validation
|
||||
|
||||
All functions throw `RangeError` on invalid coordinates:
|
||||
|
||||
```js
|
||||
import { qiblaAngle } from '@acamarata/qibla';
|
||||
|
||||
try {
|
||||
qiblaAngle(200, 0); // lat out of range
|
||||
} catch (err) {
|
||||
console.error(err.message); // "lat must be in range [-90, 90]"
|
||||
}
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
- [API Reference](../API-Reference) — full function and constant documentation
|
||||
- [Advanced Guide](advanced) — compass overlay, map integration, path interpolation
|
||||
Loading…
Reference in a new issue