diff --git a/README.md b/README.md index b419470..a3877bf 100644 --- a/README.md +++ b/README.md @@ -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" } } ``` @@ -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. \ No newline at end of file diff --git a/src/Distance.php b/src/Distance.php index 9c9a1fb..d0eb5c2 100644 --- a/src/Distance.php +++ b/src/Distance.php @@ -47,6 +47,7 @@ class Distance * @param float $longitudeB The longitude for point B. * * @uses betweenVincenty + * @uses betweenHaversine * @throws Exception * @return float */ @@ -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 @@ -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.'); } diff --git a/tests/DistanceTest.php b/tests/DistanceTest.php index db45a81..e05abdd 100644 --- a/tests/DistanceTest.php +++ b/tests/DistanceTest.php @@ -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'); @@ -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)); + } } \ No newline at end of file