Skip to content

Commit

Permalink
Added support for the Haversine formula.
Browse files Browse the repository at this point in the history
  • Loading branch information
ldebrouwer committed May 1, 2015
1 parent e7b84b4 commit 7526916
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ When using [Composer](https://getcomposer.org) you can always load in the latest
```bash
{
"require": {
"ldebrouwer/distance": "dev-master"
"ldebrouwer/distance": "~0.2"
}
}
```
Expand All @@ -27,6 +27,5 @@ Check it out [on Packagist](https://packagist.org/packages/ldebrouwer/distance).
This is still on the to-do list. The code is pretty well documented though and should autocomplete in most IDEs.

## Still to come
- Haversine formula support.
- Expanded unit support.
- Documentation.
26 changes: 25 additions & 1 deletion src/Distance.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Distance
* @param float $longitudeB The longitude for point B.
*
* @uses betweenVincenty
* @uses betweenHaversine
* @throws Exception
* @return float
*/
Expand Down Expand Up @@ -87,6 +88,29 @@ private function betweenVincenty($latitudeA, $longitudeA, $latitudeB, $longitude
return floor($angle * 6371000);
}

/**
* Method that returns the distance between two GPS locations in meters according to the Haversine formula.
*
* @param float $latitudeA The latitude for point A.
* @param float $longitudeA The longitude for point A.
* @param float $latitudeB The latitude for point B.
* @param float $longitudeB The longitude for point B.
*
* @return float
*/
private function betweenHaversine($latitudeA, $longitudeA, $latitudeB, $longitudeB)
{
$latitudeA = deg2rad($latitudeA);
$longitudeA = deg2rad($longitudeA);
$latitudeB = deg2rad($latitudeB);
$longitudeB = deg2rad($longitudeB);
$latDelta = $latitudeB - $latitudeA;
$longDelta = $longitudeB - $longitudeA;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) + cos($latitudeA) * cos($latitudeB) * pow(sin($longDelta / 2), 2)));

return floor($angle * 6371000);
}

/**
* @param $distance
* @return mixed
Expand Down Expand Up @@ -115,7 +139,7 @@ public function getFormula()
*/
public function setFormula($formula)
{
if (!in_array($formula, ['vincenty'])) {
if (!in_array($formula, ['vincenty', 'haversine'])) {
throw new Exception('You have tried to set an invalid distance formula.');
}

Expand Down
36 changes: 34 additions & 2 deletions tests/DistanceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ public function testInvalidParams()
}

/**
* Test the retrieval of the distance between the Apple and Google campuses.
* Test the retrieval of the distance between the Apple and Google campuses using the Vincenty formula.
*/
public function testDistanceBetweenAppleAndGoogle()
public function testDistanceBetweenAppleAndGoogleUsingVincenty()
{
$distance = new Distance();
$distance->setUnit('m');
Expand Down Expand Up @@ -97,4 +97,36 @@ public function testDistanceBetweenAppleAndGoogle()

$this->assertEquals(439527.5586068, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));
}

/**
* Test the retrieval of the distance between the Apple and Google campuses using the Haversine formula.
*/
public function testDistanceBetweenAppleAndGoogleUsingHaversine()
{
$distance = new Distance();
$distance->setUnit('m');
$distance->setFormula('haversine');

$this->assertEquals(11164, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));

$distance->setUnit('km');

$this->assertEquals(11.164, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));

$distance->setUnit('mi');

$this->assertEquals(6.936987987488, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));

$distance->setUnit('cm');

$this->assertEquals(1116400, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));

$distance->setUnit('ft');

$this->assertEquals(36627.2966436, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));

$distance->setUnit('in');

$this->assertEquals(439527.5586068, $distance->between(37.331741, -122.030333, 37.422546, -122.084250));
}
}

0 comments on commit 7526916

Please sign in to comment.