From 1117e29c697b54eb05279b73b62515de1595dbb2 Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Sun, 28 Jan 2018 14:18:37 -0800 Subject: [PATCH] add geo functions --- README.md | 1 + composer.json | 3 +- src/geo.php | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/geo.php diff --git a/README.md b/README.md index 2193a22..09d3b71 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This project provides several helpful utilities for working with PHP projects, a * `p3k\url` - helpful functions for parsing and building URLs * `p3k\cache` - a simple caching helper backed by Redis * `p3k\utils` - miscellaneous functions +* `p3k\geo` - geo functions for calculating distance and other things * `p3k\global` - sets the timezone to UTC (you're already storing all your dates in UTC, right?) PHP Support diff --git a/composer.json b/composer.json index 3b6e4b1..3f92399 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ "src/url.php", "src/utils.php", "src/date.php", - "src/cache.php" + "src/cache.php", + "src/geo.php" ] }, "autoload-dev": { diff --git a/src/geo.php b/src/geo.php new file mode 100644 index 0000000..ff265cf --- /dev/null +++ b/src/geo.php @@ -0,0 +1,93 @@ +_perpendicularDistance($pointList[$i][0], $pointList[$i][1], + $pointList[0][0], $pointList[0][1], + $pointList[$totalPoints-1][0], $pointList[$totalPoints-1][1]); + + if ($d > $dmax) + { + $index = $i; + $dmax = $d; + } + } + + $resultList = array(); + + // If max distance is greater than epsilon, recursively simplify + if ($dmax >= $epsilon) + { + // Recursive call + $recResults1 = $this->_ramerDouglasPeucker(array_slice($pointList, 0, $index + 1), $epsilon); + $recResults2 = $this->_ramerDouglasPeucker(array_slice($pointList, $index, $totalPoints - $index), $epsilon); + + // Build the result list + $resultList = array_merge(array_slice($recResults1, 0, count($recResults1) - 1), + array_slice($recResults2, 0, count($recResults2))); + } + else + { + $resultList = array($pointList[0], $pointList[$totalPoints-1]); + } + // Return the result + return $resultList; +} + + +// http://www.loughrigg.org/rdp/ + +//The author has placed this work in the Public Domain, thereby relinquishing all copyrights. +//You may use, modify, republish, sell or give away this work without prior consent. +//This implementation comes with no warranty or guarantee of fitness for any purpose. + +//========================================================================= +//An implementation of the Ramer-Douglas-Peucker algorithm for reducing +//the number of points on a polyline +//see http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm +//========================================================================= + +//Finds the perpendicular distance from a point to a straight line. +//The coordinates of the point are specified as $ptX and $ptY. +//The line passes through points l1 and l2, specified respectively with their +//coordinates $l1x and $l1y, and $l2x and $l2y +function perpendicularDistance($ptX, $ptY, $l1x, $l1y, $l2x, $l2y) +{ + $result = 0; + if ($l2x == $l1x) + { + //vertical lines - treat this case specially to avoid divide by zero + $result = abs($ptX - $l2x); + } + else + { + $slope = (($l2y-$l1y) / ($l2x-$l1x)); + $passThroughY = (0-$l1x)*$slope + $l1y; + $result = (abs(($slope * $ptX) - $ptY + $passThroughY)) / (sqrt($slope*$slope + 1)); + } + return $result; +} + +// Calculate the Great Circle distance between two points, in meters +function gc_distance($lat1, $lng1, $lat2, $lng2) { + return ( 6378100 * acos( cos( deg2rad($lat1) ) * cos( deg2rad($lat2) ) * cos( deg2rad($lng2) - deg2rad($lng1) ) + sin( deg2rad($lat1) ) * sin( deg2rad($lat2) ) ) ); +}