From 84f81538c5e589b091347c692be4edf4530dc0e1 Mon Sep 17 00:00:00 2001 From: "Donald A. Lobo" Date: Wed, 4 Dec 2013 06:29:55 -0800 Subject: [PATCH] CRM-13904 - Improve proximity query accuracy http://issues.civicrm.org/jira/browse/CRM-13904 --- CRM/Contact/BAO/ProximityQuery.php | 73 ++++++++---------------------- 1 file changed, 18 insertions(+), 55 deletions(-) diff --git a/CRM/Contact/BAO/ProximityQuery.php b/CRM/Contact/BAO/ProximityQuery.php index 87b14ab591..8f1295ff1d 100644 --- a/CRM/Contact/BAO/ProximityQuery.php +++ b/CRM/Contact/BAO/ProximityQuery.php @@ -116,24 +116,6 @@ class CRM_Contact_BAO_ProximityQuery { return deg2rad($angle) * self::earthRadius($latitude); } - /** - * Estimate the earth-surface distance between two locations. - */ - static function earthDistance($longitudeSrc, $latitudeSrc, - $longitudeDst, $latitudeDst - ) { - - $longSrc = deg2rad($longitudeSrc); - $latSrc = deg2rad($latitudeSrc); - $longDst = deg2rad($longitudeDst); - $latDst = deg2rad($latitudeDst); - - $radius = self::earthRadius(($latitudeSrc + $latitudeDst) / 2); - - $cosAngle = cos($latSrc) * cos($latDst) * (cos($longSrc) * cos($longDst) + sin($longSrc) * sin($longDst)) + sin($latSrc) * sin($latDst); - return acos($cosAngle) * $radius; - } - /** * Estimate the min and max longitudes within $distance of a given location. */ @@ -198,55 +180,36 @@ class CRM_Contact_BAO_ProximityQuery { ); } - /* - * Returns the SQL fragment needed to add a column called 'distance' - * to a query that includes the location table - * - * @param $longitude - * @param $latitude - */ - - static function earthDistanceSQL($longitude, $latitude) { - $long = deg2rad($longitude); - $lat = deg2rad($latitude); - $radius = self::earthRadius($latitude); - - $cosLong = cos($long); - $cosLat = cos($lat); - $sinLong = sin($long); - $sinLat = sin($lat); - - return " -IFNULL( ACOS( $cosLat * COS( RADIANS( $latitude ) ) * - ( $cosLong * COS( RADIANS( $longitude ) ) + - $sinLong * SIN( RADIANS( $longitude ) ) ) + - $sinLat * SIN( RADIANS( $latitude ) ) ), 0.00000 ) * $radius -"; - } - static function where($latitude, $longitude, $distance, $tablePrefix = 'civicrm_address') { self::initialize(); $params = array(); $clause = array(); - list($minLongitude, $maxLongitude) = self::earthLongitudeRange($longitude, - $latitude, - $distance - ); - list($minLatitude, $maxLatitude) = self::earthLatitudeRange($longitude, - $latitude, - $distance - ); - - $earthDistanceSQL = self::earthDistanceSQL($longitude, $latitude); + list($minLongitude, $maxLongitude) = + self::earthLongitudeRange($longitude, + $latitude, + $distance + ); + list($minLatitude, $maxLatitude) = + self::earthLatitudeRange( + $longitude, + $latitude, + $distance + ); $where = " {$tablePrefix}.geo_code_1 >= $minLatitude AND {$tablePrefix}.geo_code_1 <= $maxLatitude AND {$tablePrefix}.geo_code_2 >= $minLongitude AND {$tablePrefix}.geo_code_2 <= $maxLongitude AND -$earthDistanceSQL <= $distance +ACOS( + COS(RADIANS({$tablePrefix}.geo_code_1)) * + COS(RADIANS($latitude)) * + COS(RADIANS({$tablePrefix}.geo_code_2) - RADIANS($longitude)) + + SIN(RADIANS({$tablePrefix}.geo_code_1)) * + SIN(RADIANS($latitude)) + ) * 6378137 <= $distance "; return $where; -- 2.25.1