Geo Helper¶
Nene\Func\GeoHelper — geographic distance calculation and bounding box using the Haversine formula.
API¶
| Method | Description |
|---|---|
distanceKm(float $lat1, float $lon1, float $lat2, float $lon2): float |
Great-circle distance in kilometres. |
distanceMi(float $lat1, float $lon1, float $lat2, float $lon2): float |
Great-circle distance in miles. |
boundingBox(float $lat, float $lon, float $radiusKm): array |
Bounding box for proximity pre-filter. |
Usage¶
// Distance between Tokyo and Osaka
$km = GeoHelper::distanceKm(35.6895, 139.6917, 34.6937, 135.5023); // ≈ 396 km
$mi = GeoHelper::distanceMi(35.6895, 139.6917, 34.6937, 135.5023); // ≈ 246 mi
// Symmetric
GeoHelper::distanceKm(A, B) === GeoHelper::distanceKm(B, A)
// Bounding box for "within 10 km of Tokyo" proximity search
$box = GeoHelper::boundingBox(35.6895, 139.6917, 10.0);
// $box = ['minLat' => 35.5993, 'maxLat' => 35.7797, 'minLon' => 139.5737, 'maxLon' => 139.8097]
// Use in SQL as a fast pre-filter
$stmt = $pdo->prepare(
'SELECT * FROM spots
WHERE lat BETWEEN :minLat AND :maxLat
AND lon BETWEEN :minLon AND :maxLon'
);
$stmt->execute($box);
// Then apply exact Haversine to filter by true distance
$results = array_filter($rows, fn ($row) =>
GeoHelper::distanceKm($centerLat, $centerLon, $row['lat'], $row['lon']) <= 10.0
);
Bounding box pattern¶
The bounding box is a fast rectangular pre-filter. It over-selects (corners of the box extend beyond the circle) but is cheap to compute and index-friendly in SQL. Always combine with exact distance filtering for accurate results.
Formula¶
Uses the Haversine formula for great-circle distances on a sphere (Earth radius = 6371 km). Accurate to within ~0.3% for distances up to thousands of kilometres.
Key design points¶
- Static helper: no state or DB dependency — pure math.
- No external dependencies: standard PHP math functions only.
- Coordinate order:
(lat, lon)— not(lon, lat)as used by some GeoJSON libraries. - Boundary clamping:
boundingBox()clamps output to valid ranges (-90..90 lat, -180..180 lon).