Keywords: PHP | Coordinate Distance | Haversine Formula | Vincenty Formula | Geocoding
Abstract: This technical article provides a comprehensive guide to calculating the great-circle distance between two geographic coordinates using PHP. It covers the Haversine and Vincenty formulas, with detailed code implementations, accuracy comparisons, and references to external libraries for simplified usage. Aimed at developers seeking efficient, API-free solutions for geospatial calculations.
Introduction
Calculating the distance between two geographic coordinates is a fundamental task in applications such as navigation, logistics, and web services. In PHP, this can be efficiently achieved using mathematical formulas without relying on external APIs, ensuring data privacy and reducing dependencies. This article explores the implementation of the Haversine and Vincenty formulas for computing great-circle distances, providing step-by-step code examples, accuracy analyses, and practical insights for developers.
Haversine Formula
The Haversine formula is a widely used method for calculating the distance between two points on a sphere, such as the Earth. It is based on the law of haversines and offers good accuracy for most practical purposes, though it may encounter rounding errors with antipodal points due to the spherical Earth model. The formula accounts for the Earth's curvature using trigonometric functions.
The mathematical expression involves: a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2), where Δφ is the difference in latitude, Δλ is the difference in longitude, and φ1, φ2 are the latitudes. Then, c = 2 ⋅ atan2(√a, √(1−a)), and the distance d = R ⋅ c, with R representing the Earth's radius.
Implementation of Haversine in PHP
Based on the accepted answer, here is a refined implementation of the Haversine formula in PHP. This function accepts latitude and longitude in degrees and returns the distance in meters by default, with the Earth radius parameter allowing flexibility for other units.
function haversineGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000) {
// Convert degrees to radians
$latFrom = deg2rad($latitudeFrom);
$lonFrom = deg2rad($longitudeFrom);
$latTo = deg2rad($latitudeTo);
$lonTo = deg2rad($longitudeTo);
// Calculate differences in coordinates
$latDelta = $latTo - $latFrom;
$lonDelta = $lonTo - $lonFrom;
// Apply Haversine formula
$a = sin($latDelta / 2) * sin($latDelta / 2) + cos($latFrom) * cos($latTo) * sin($lonDelta / 2) * sin($lonDelta / 2);
$c = 2 * asin(sqrt($a));
return $c * $earthRadius;
}
This implementation efficiently computes distances and can be integrated into PHP applications. The default Earth radius is set to 6371000 meters, corresponding to the mean radius, but it can be adjusted for units like kilometers or miles by modifying the parameter.
Vincenty Formula
For higher accuracy, particularly over long distances or near antipodal points, the Vincenty formula is recommended. It uses an iterative approach based on an ellipsoidal Earth model, minimizing errors and providing superior precision in geodesic calculations.
The formula involves more complex trigonometric operations but is essential for scientific and high-precision applications where Haversine may fall short.
Implementation of Vincenty in PHP
Here is a PHP implementation of the Vincenty formula, adapted from the provided answer. It accepts coordinates in degrees and returns the distance in meters, with the Earth radius customizable for different units.
function vincentyGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000) {
// Convert degrees to radians
$latFrom = deg2rad($latitudeFrom);
$lonFrom = deg2rad($longitudeFrom);
$latTo = deg2rad($latitudeTo);
$lonTo = deg2rad($longitudeTo);
$lonDelta = $lonTo - $lonFrom;
$a = pow(cos($latTo) * sin($lonDelta), 2) + pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2);
$b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta);
$angle = atan2(sqrt($a), $b);
return $angle * $earthRadius;
}
This code avoids issues with antipodal points by using the atan2 function for stable angle calculations, making it more reliable for global distance computations.
Comparison and Discussion
Both formulas have distinct advantages and limitations. Haversine is simpler, faster, and sufficient for most use cases, such as short to medium distances in web applications. Vincenty, while computationally intensive, offers enhanced accuracy for long distances and is preferred in geodesy.
In practice, the choice depends on required precision and performance constraints. For real-time applications, Haversine is often favored for its speed, whereas Vincenty is better suited for scientific analyses.
Additionally, alternative methods like the spherical law of cosines, as seen in other answers, provide different approaches. Here is an implementation that allows unit selection:
function distance($lat1, $lon1, $lat2, $lon2, $unit) {
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
} else if ($unit == "N") {
return ($miles * 0.8684);
} else {
return $miles;
}
}
This function returns distances in miles, kilometers, or nautical miles based on the input unit, using different constants that may affect accuracy compared to Haversine.
Unit Conversion and Earth Radius
The Earth is not a perfect sphere, so the mean radius—approximately 6371 kilometers or 3959 miles—is commonly used. In the implementations, the Earth radius parameter enables flexibility; for example, setting it to 3959 * 1609.344 (meters in a mile) yields distances in miles. However, handling unit conversions separately, as in the alternative function, is often more straightforward.
Using SI units (e.g., meters) is recommended for consistency in scientific contexts, reducing potential errors in calculations.
Third-Party Libraries
For developers seeking pre-built solutions, PHP libraries like Distical simplify distance calculations. As referenced in the auxiliary article, Distical is a Composer-based library offering an object-oriented interface for easy integration.
Example usage:
// Install via Composer: composer require ballen/distical
require_once 'vendor/autoload.php';
use Ballen\Distical\Calculator as DistanceCalculator;
use Ballen\Distical\Entities\LatLong;
$point1 = new LatLong(52.057941, 1.147172);
$point2 = new LatLong(51.507608, -0.127822);
$distance = (new DistanceCalculator($point1, $point2))->get()->asMiles();
echo "Distance: " . $distance . " miles";
This library abstracts the underlying calculations, supports multiple units, and includes features like multi-point distance computations, making it ideal for rapid development. It is unit-tested and compatible with various PHP versions.
Conclusion
Implementing distance calculations in PHP using the Haversine or Vincenty formulas is effective and accessible. Haversine is suitable for general applications, while Vincenty provides higher accuracy for specialized needs. External libraries like Distical can further streamline the process. Developers should select the method based on accuracy requirements, performance considerations, and ease of implementation to optimize their geospatial solutions.