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

Était-ce utile?

La 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.

Autres conseils

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top