简体   繁体   English

Geokit Rails - 查找包含其范围内的点(位置)的所有用户

[英]Geokit Rails - find all users who contain a point(location) in their range

Trying to understand how can I use Geokit Rails to get all users who covers a certain point with their coverage range. 试图了解如何使用Geokit Rails来覆盖覆盖范围的所有用户。

For example users A, B, C and D has a radius of i > 0 km. 例如,用户A,B,C和D的半径为i> 0km。 Now let's say I want to find all users who cover a selected point on map created with lat and lng. 现在让我们说我想找到覆盖用lat和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. 从图像:应该返回用户A,B,C而不是D,因为红点不在他的范围内。

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. 谢谢。

问题的图形描述

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. 它是如何工作的 :用户表有一个名为distance的字段,我保留一个整数,显示用户覆盖的半径,例如:20。在进行搜索时,我从表单中发送lat和long params以查找位置映射,然后只是循环通过用户来查找它们之间的距离和此点之间的距离小于距离值的所有用户。

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. 例如:用户1的范围为20 km,因此距离值为20,然后检查用户1和地图上的点之间的距离是否小于20加载数组。

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. 我不需要太多的用户循环,因为我在之前的代码中限制它们的数量所以我只得到它们中的一些...最多1到40之间。

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. 在上述情况下, longitudelatitude是搜索模型的属性,但也可以是任何其他属性。

Try using the distance_sql method. 尝试使用distance_sql方法。

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. 我们假设问题中的用户模型已经使用acts_as_mappable定义,并且有一个名为range的列,用于定义用户的范围(以kms为单位)。 Let's say that the selected location in your query is defined by a model called Location, that also acts_as_mappable . 假设查询中的选定位置由名为Location的模型定义,该模型也是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: 如果您有一个名为my_location的Location实例,那么您可以找到其范围包含该位置的所有用户,如下所示:

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. distance_sql方法期望其第一个参数响应latlng方法,因此acts_as_mappable的模型是理想的。 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. 如果您选择的位置只是[lat,lng]的数组,那么遗憾的是这种方法无法使用 - 您必须将它包装在一个响应latlng方法的类中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM