CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Support »
  • Using CiviCRM »
  • Using Core CiviCRM Functions (Moderator: Yashodha Chaku) »
  • CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
Pages: [1]

Author Topic: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search  (Read 1504 times)

yasheshb

  • I post occasionally
  • **
  • Posts: 72
  • Karma: 5
CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
November 29, 2010, 01:14:07 am
Hello,

   I've been trying to add the "Distance" from target as a field to the list of fields
that i want to display in the search result. Unable to add it so far.

  The distance field would calculate the actual distance of the Contact from the Target Location
and would be displayed as a sortable field in the Search Results.

Any help, pointers are appreciated.

Thanks.

Yashesh Bhatia.

JoeMurray

  • Administrator
  • Ask me questions
  • *****
  • Posts: 578
  • Karma: 24
    • JMA Consulting
  • CiviCRM version: 4.4 and 4.5 (as of Nov 2014)
  • CMS version: Drupal, WordPress, Joomla
  • MySQL version: MySQL 5.5, 5.6, MariaDB 10.0 (as of Nov 2014)
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
November 29, 2010, 07:42:56 am
You'll need to do some coding - take a look at CRM/Contact/BAO/ProximityQuery.php. It appears CiviCRM does not rely on MySQL's GIS functionality since it may not be installed, and does all the calculations itself in a rough and ready way. Note that the code is already adding a distance column to the query, so you'll just need to display that and make it searchable.
Co-author of Using CiviCRM https://www.packtpub.com/using-civicrm/book

yasheshb

  • I post occasionally
  • **
  • Posts: 72
  • Karma: 5
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
November 29, 2010, 10:04:37 pm
Joe Murray:

  Thanks for the reply. I studied the CRM/Contact/BAO/ProximityQuery.php yesterday and went thru it today too.
What function are you referring to which adds the distance from contact id to the actual target location ?

  After putting breakpoints i noticed the code goes through the function

Code: [Select]
Nov 30 11:29:58  [info] entering function where() in ProximityQuery.php
Nov 30 11:29:58  [info] $distance = 8046.72

Also, i did put a breakpoint in alterRow

Code: [Select]
Nov 30 11:29:58  [info] entering function alterRow() in ProximityNJAPM.php
Nov 30 11:29:58  [info] $row = Array
(
    [sort_name] => Foobar
    [street_address] => 111 Foo, Bldg. 1, Suite 111
    [city] => Princeton
    [state_province] => New Jersey
    [postal_code] => 08540
    [country] => United States
    [geo_code_1] => 40.32437
    [geo_code_2] => -74.636905
    [phone] => 111-111-1111
    [email] => foo@bar.com
    [website_url] => http://foobar.com
    [profession] => Foo
    [firm_name] => Foobar
    [title] =>
    [checkbox] => mark_x_1100
    [action] => <span><a href="http://www.foobar.com/civicrm/contact/view?reset=1&amp;cid=1100" class="action-item action-item-first" title="View Contact Details"  >View</a><a href="http://www.foobar.com/civicrm/contact/add?reset=1&amp;action=update&amp;cid=1100" class="action-item" title="Edit Contact Details"  >Edit</a></span>
    [contact_id] => 1100
)

but could not find the actual distance of the Contact to the Target.

Can you please point out the exact function in sites/all/modules/civicrm/CRM/Contact/BAO/ProximityQuery.php

Here's a list of functions i have in my code for the above class

Code: [Select]
[njapm@bfc33 BAO]$ grep function ProximityQuery.php
     * All function arguments and return values measure distances in metres
    static function initialize( ) {
    static function earthRadius( $latitude ) {
    static function earthXYZ( $longitude, $latitude, $height = 0 ) {
    static function earthArcLength( $angle, $latitude ) {
    static function earthDistance( $longitudeSrc, $latitudeSrc,
    static function earthLongitudeRange( $longitude, $latitude, $distance ) {
    static function earthLatitudeRange( $longitude, $latitude, $distance ) {
    static function earthDistanceSQL( $longitude, $latitude ) {
    static function where( $latitude, $longitude, $distance, $tablePrefix = 'civicrm_address' ) {
      Logger::le_function();
        Logger::ll_function();
    static function process( &$query, &$values ) {
      Logger::le_function();
        Logger::ll_function();


Thanks for your help. Appreciate it.

Yashesh Bhatia

yasheshb

  • I post occasionally
  • **
  • Posts: 72
  • Karma: 5
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
December 01, 2010, 09:22:16 am
Hi.

  I was able to get the Distance field in here by doing the following in my custom search code.
by doing the following

1 - in the constructor add the column

Code: [Select]
      $this->_columns = array( ts('Click on name to locate map') => 'sort_name'      ,
                               ts('Street Address'             ) => 'street_address' ,
                               ts('City'                       ) => 'city'           ,
                               ts('State'                      ) => 'state_province' ,
                               ts('Zip Code'                   ) => 'postal_code'    ,
                               ts('Country'                    ) => 'country'        ,
                               ts('Distance'                   ) => 'distance'       ,

2 - in the function 'all' add the distance column to the SELECT clause
Code: [Select]
function all($offset=0, $rowcount=0, $sort=null, $includeContactIDs=false) {
.
.
      $selectClause = <<<EOD
contact_a.id                  as contact_id    ,
contact_a.sort_name      as sort_name     ,
address.street_address    as street_address,
address.city                   as city          ,
state_province.name       as state_province,
address.postal_code        as postal_code   ,
country.name                 as country,
0                                 as distance,


3 - and adding the value for distance in the alterRow function
Code: [Select]
    function alterRow( &$row ) {
      require_once 'CRM/Contact/BAO/ProximityQuery.php';
      $distance = CRM_Contact_BAO_ProximityQuery::earthDistance($row['geo_code_2'], $row['geo_code_1'], $this->_longitude, $this->_latitude);
      $row['distance'] = $distance/1609.344;
    }

This does give the distance but it does not give me the desired results
for example if one goes to

http://njapm.venuslabs.co.in/civicrm/contact/search/custom?reset=1&csid=18

and
enters 08520 for the Zip Code
and 5 mile radius
it does show rows which have a distance of more than 5 miles.

any pointers on how to debug/fix the error above in the distance calculation ?

thx.

yashesh.

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
December 01, 2010, 09:57:18 am

hey yashesh:

as the comments indicate most of that code has been "borrowed" from the drupal location module. You might want to check if there are any bug fixes / improvements to that code

I suspect none of us understand those calculations too much. If you do improve it, please submit your changes back to the core :)

thanx

lobo
A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

yasheshb

  • I post occasionally
  • **
  • Posts: 72
  • Karma: 5
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
December 02, 2010, 01:35:13 am
hi Lobo,

 thx for the input. I did poke around a bit today an wrote another function in ProximityQuery to use the Haversine formula to calculate the earthdistance.
That also gave similar results as the earthDistance.

  I suspect the query WHERE clause which is used for filtering the results seems to be incorrect, but this is a hunch.

Code: [Select]
        return "
IFNULL( ACOS( $cosLat * COS( RADIANS( $latitude ) ) *
              ( $cosLong * COS( RADIANS( $longitude ) ) +
                $sinLong * SIN( RADIANS( $longitude ) ) ) +
              $sinLat  * SIN( RADIANS( $latitude  ) ) ), 0.00000 ) * $radius
";

also, here's the function for haversine which i added to ProximityQuery on my local install.


Code: [Select]
/**
 * Estimate the earth-surface distance between two locations.
 */
static function earthDistanceHaversine( $longitudeSrc, $latitudeSrc, $longitudeDst, $latitudeDst ) {
  $longSrc = deg2rad( $longitudeSrc );
  $latSrc  = deg2rad( $latitudeSrc  );
  $longDst = deg2rad( $longitudeDst );
  $latDst  = deg2rad( $latitudeDst  );
  $radius = self::earthRadius( ( $latitudeSrc + $latitudeDst ) / 2 );

  /**
     This uses the ‘haversine’ formula to calculate great-circle distances between
     the two points – that is, the shortest distance over the earth’s surface – giving
     an ‘as-the-crow-flies’ distance between the points (ignoring any hills!).

     Haversine formula:

     R = earth’s radius (mean radius = 6,371km)
     Δlat = lat2− lat1
     Δlong = long2− long1
     a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
     c = 2.atan2(√a, √(1−a))
     d = R.c

     (Note that angles need to be in radians to pass to trig functions).
  */

  $deltaLat  = $latDst  - $latSrc;
  $deltaLong = $longDst - $longSrc;
  $a = pow(sin($deltaLat/2), 2) + (cos($latSrc) * cos($latDst) * pow(sin($deltaLong/2), 2));
  $c = 2 * atan2(sqrt($a), sqrt(1-$a));
  $d = $radius * $c;
  return $d;
}

thx.

yashesh

jpcote

  • I’m new here
  • *
  • Posts: 2
  • Karma: 1
  • CiviCRM version: 3.2
  • CMS version: Drupal
  • MySQL version: 5
  • PHP version: 5.2
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
October 31, 2011, 09:50:59 am
A client of ours - a large foodbank - wanted to be able to sort the Proximity results ranked by the closeness of the result. They wanted to help their clients in finding the closest resource to their home. After some searching I found some information on taking the geo_code and converting them into distances. I adapted it for use in this project.

The links where I had initially found a technique for calculating the distances no longer contain that information, so I wonder now if it is a good technique or not. I do know that through testing, the calculated distances where close to distances on a map. The distances are a point to point distance and do not take into account the actual road/path that the clients would follow to get between their homes and the depot.

The calculation for distance:

ROUND(SQRT(POW((53.5362308-geo_code_1),2)+POW((-113.5762697-geo_code_2),2))*100,1)


In order to use the calculation, copy, modify and override the CRM/Contact/Form/Search/Custom/Proximity.php file:

This will add the distance variable to the search results.


   function __construct( &$formValues ) {
       ...
       $this->_columns = array( ts('Distance')       => 'distance'       ,



   function all( $offset = 0, $rowcount = 0, $sort = null,
                 $includeContactIDs = false ) {
       ...
       $selectClause = "
       ...
ROUND(SQRT(POW((".$this->_latitude."-geo_code_1),2)+POW((".$this->_longitude."-geo_code_2),2))*100,1) AS distance
";



   function where( $includeContactIDs = false ) {
       ...
       $where .= " AND ROUND(SQRT(POW((".$this->_latitude."-geo_code_1),2)+POW((".$this->_longitude."-geo_code_2),2))*100,1) <= ".( $this->_distance / 1000 );


This code calculates the distance between the two points and sets the result.

Apparantly using code tags caused the error "Sorry, you are not allowed to post external links."

(jeff at freeform dot ca)
(Freeform Solutions)

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search
October 31, 2011, 03:11:13 pm

hey jeff:

thanx for the detailed post and explanation. Would be great if you can:

1. create a patch for this proximity search
2. File an issue on http://issues.civicrm.org/ and attach the patch to it.

If you do so this week, we'll make an attempt to get it into 4.1 :)

lobo

A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

Pages: [1]
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Support »
  • Using CiviCRM »
  • Using Core CiviCRM Functions (Moderator: Yashodha Chaku) »
  • CiviCRM 3.2.0 - "Distance" from target as field in Proximity Search

This forum was archived on 2017-11-26.