Question

Trying to understand how can I use Geokit Rails to get all users who covers a certain point with their coverage range.

For example users A, B, C and D has a radius of i > 0 km. Now let's say I want to find all users who cover a selected point on map created with lat and lng. So it's not the issue when I want to find all records within a range, it's the case where I want to find all records who include my location in their range.

From image: should return User A, B, C and not D as the red dot is not in his range.

What I have tried: I've looked in the docs from top to bottom, searched for examples but all leads to finding records in a range, so it's not my case. If any one had the same thing to solve please share. Thank you.

graphic description of the problem

Was it helpful?

Solution

My solution that works for now, may be not the best one, just can't find any other:

  address = [lat, long]
  users.each do |u|
    if u.distance_to(address, :units => :kms) < u.distance
      tutors << t
    end
  end 

how it works: User table has a field called distance where I keep an integer that shows what is the radius that user covers, for ex: 20. When doing a search I am sending lat and long params from the form to find a position on map, and then just loop trough users to find all users where distance between them and this point is less than the distance value.

For example: User 1 has a range of 20 km, so distance value is 20, then check if distance between User 1 and point on map is less than 20 load him in array.

I wouldn't have to much users to loop through as I limit their number in the code that goes before this so I get only a few of them.. between 1 and 40 max.

For now it works, if anyone has a better solution please share.

A better sollution:

  def find_tutors
    lat_d = Geokit::Mappable::LATITUDE_DEGREES
    km_lat = Geokit::Mappable::KMS_PER_LATITUDE_DEGREE
    kms_per_mile = Geokit::Mappable::KMS_PER_MILE

    users = User.joins(:courses).where("courses.lesson ILIKE ?", "%#{lesson}%")

    if long.present?
      users = users.where("pow((longitude - ?) * (#{lat_d} * #{kms_per_mile} * abs(cos(0.0174 * longitude))), 2) +
      pow((latitude  - ?) * #{km_lat}, 2) < pow(distance, 2)",
      long, lat)
    end

    users
  end

In the case above longitude and latitude are attributes of search model, but could be also any other attributes.

OTHER TIPS

Try using the distance_sql method.

We'll assume that the User model in the question is already defined using acts_as_mappable, and has a column called range that defines the user's range in kms. Let's say that the selected location in your query is defined by a model called Location, that also acts_as_mappable.

If you have an instance of a Location called my_location, then you can find all Users whose range includes that location like this:

User.where( User.distance_sql( my_location, :kms ) + " < range" )

The distance_sql method expects its first parameter to respond to the lat and lng methods, so a model that acts_as_mappable is ideal. If your selected location is just an array of [lat,lng], that unfortunately won't work with this method - you'll have to wrap it in a class which responds to the lat and lng methods first.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top