geocoder icon indicating copy to clipboard operation
geocoder copied to clipboard

Feature Request - Add geocoded table/model reference to near() method

Open joshm1204 opened this issue 6 years ago • 3 comments

FEATURE REQUEST: (as referenced in this closed issue: https://github.com/alexreisner/geocoder/issues/1391

Add geocoded table/model reference to Near(), so you do not need to query directly on the geocoded model.

User.joins(profile:[:address, :activity,:hobbies].near(location,distance, :address)

joshm1204 avatar Mar 22 '19 16:03 joshm1204

For now, if I understand correctly, you can accomplish this with a WHERE clause generated by the distance_sql method and specifying the table name in the column names (eg, user.latitude).

alexreisner avatar Mar 22 '19 16:03 alexreisner

Yes, I think so, basically the near command gets a

NoMethodError (undefined method `near' for #Profile::ActiveRecord_Relation:0x00007fdd7627abb8)

I will currently reconstruct the Where clause, with the following. It took me a long time to figure this out, so I hope this is helpful.

Geocoder::Calculations.bounding_box([lat,lon]) will produce the numbers for the below..

However, when I put Geocoder::Calculations.bounding_box([lat,lon], 69), I would have assumed the low latitude and high latitude boundary would be have a difference of 2, but it does not.

What am I missing? or is this a bug?

   WHERE (addresses.latitude BETWEEN 38.6728005337783 AND 39.2517276662217 
   AND addresses.longitude BETWEEN -95.62737134757229 AND -94.8828282524277 
   AND

I found your reference tutorial, which provided: 1 degree of latitude ~= 69 miles 1 degree of longitude ~= cos(latitude)*69

To calculate lon and lat for the rectangle: set lon1 = mylon-dist/abs(cos(radians(mylat))*69); set lon2 = mylon+dist/abs(cos(radians(mylat))*69); set lat1 = mylat-(dist/69); set lat2 = mylat+(dist/69);

Second, I see that Geocoder::Sql.send("full_distance",0.38962264e2, 0.952551e2,'addresses.latitude','addresses.longitude') will generate the distance calculation.

     (3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((38.9622641 - addresses.latitude) * 
    PI() / 180 / 2), 2) + COS(38.9622641 * PI() / 180) * COS(addresses.latitude * 
    PI() / 180) * POWER(SIN((-95.2550998 - addresses.longitude) * PI() / 180 / 2), 2)))) 

and I assume this is the distance 0 to 20 miles/km:

BETWEEN 0.0 AND 20) ORDER BY distance ASC

joshm1204 avatar Mar 22 '19 18:03 joshm1204

My overall solutions, but I feel there is a problem with my bounding box.

def find_near(lat,lon, radius)
  distance = Geocoder::Sql.send("full_distance",lat, lon,'addresses.latitude','addresses.longitude')
  bounding = Geocoder::Calculations.bounding_box([lat,lon],radius)

  "WHERE (addresses.latitude BETWEEN #{bounding[0]} AND #{bounding[1]} 
  AND addresses.longitude BETWEEN #{bounding[2]} AND #{bounding[3]} 
  AND #{distance}
  BETWEEN 0.0 AND #{radius})"
end

joshm1204 avatar Mar 22 '19 19:03 joshm1204