Генерация случайных координат вне и в пределах заданного радиуса от начала координат - PullRequest
0 голосов
/ 06 сентября 2018

Мне нужно сгенерировать спецификацию для своей поисковой системы, чтобы проверить, что при указании исходной точки и радиуса результаты, выходящие за пределы исходной точки моего источника, не включаются в ответ, в то время как радиус в данном радиусе в километрах

Учитывая происхождение и радиус, я хочу протестировать два "экстремальных" случая, когда я создаю две тестовые точки данных,

  • одна в пределах: на точном радиусе минусэпсилон (радиус - e от начала координат)
  • один снаружи: на точный радиус плюс эпсилон (радиус + e от начала координат)

Например, если мой радиус равен 10 кмЯ хотел бы создать точку в 10,1 км и 9,9 км от источника.

Затем я хочу запустить множество тестов, в которых я выбираю случайные точки на земле (в пределах или за пределами радиуса), чтобы проверить, что все угловые случаи хорошо обрабатываются моей поисковой системой

Япроверка кода действительно работает с Geocoder.distance_between

before do
  # Ensure our example is correct
  expect(
    Geocoder::Calculations.distance_between(origin, point_outside_radius_of_origin)
  ).to be > radius_in_km

  expect(
    Geocoder::Calculations.distance_between(origin, point_within_radius_of_origin)
  ).to be < radius_in_km
end

Например, следующий фиксированный пример проходит

Используя фиксированный пример Парижа

let(:origin) { [48.856614, 2.3522219] } # Geocoder.coordinates('Paris')
let(:radius_in_km) { 10 }
let(:point_within_radius_of_origin) { [48.801148, 2.429443] } # Geocoder.coordinates('Maisons-Alfort')
let(:point_outside_radius_of_origin) { [48.790367, 2.455572] } # Geocoder.coordinates('Créteil')

ТакЯ пытаюсь реализовать функцию для генерации случайных точек из начала координат.

С https://stackoverflow.com/a/43202522/2832282 Я каким-то образом смог создать точку в пределах заданного радиуса: (кажется, эта функция работает отлично)

# Thanks to https://stackoverflow.com/a/43202522/2832282
#
# @param lon [Float]
# @param lat [Float]
# @param max_radius [FLoat] in km
#
# @return [Pair<Float>] [Lng, lat]
def random_point_within_radius_of_origin(lng:, lat:, max_radius:)
  dx, dy = Utility.random_point_in_disk(max_radius)
  random_lat = lat + dy / OneDegree
  random_lng = lng + dx / ( OneDegree * Math::cos(lat * Math::PI / 180) )
  [random_lng, random_lat]
end
# @param max_radius [Float] Distance in km
#
# @return [Pair<Float>]
def random_point_in_disk(max_radius)
  r = max_radius * rand**0.5
  theta = rand * 2 * Math::PI
  [r * Math.cos(theta), r * Math.sin(theta)]
end

Мне нужно для реализациинижеприведенная функция для генерации случайной точки вне радиуса от начала координат (мне все равно, равномерно ли оно распределено или нет) за пределами данного диска.Я думаю, я мог бы создать поддельную точку и повторить попытку, пока не достигну цели.

Обратите внимание, что если у вас есть код, который работает без указания max_radius, это даже лучше (я просто хочу исключитькоординаты, сгенерированные вышеупомянутой функцией)

# @param lon [Float] Longitude of origin
# @param lat [Float] Latitude of origin
# @param max_radius [FLoat] Max radius from origin in km
# @param min_radius [FLoat] Min radius from origin in km
#
# @return [Pair<Float>] [Lng, lat] of some random point between min_radius and max_radius of origin
def random_point_within_radius_band_of_origin(lng:, lat:, max_radius:, min_radius:)
  # What this SO Question is about
end

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Совсем просто объединить код Северина для генерации случайной точки в пределах полосы с кодом из random_point_within_radius_of_origin:

# @param min_radius [Float] Minimum radius, in km
# @param max_radius [Float] Maximum radius, in km
#
# @return [Pair<Float>]
def random_point_in_band(min_radius, max_radius)
  r     = min_radius + (max_radius - min_radius) *  Math.sqrt(rand)
  theta = 2.0 * Math::PI * rand
  [r * Math.cos(theta), r * Math.sin(theta)]
end

EarthRadius = 6371 # km
OneDegree = EarthRadius * 2 * Math::PI / 360 * 1000 # 1° latitude in meters

# @param lon [Float] Longitude of origin
# @param lat [Float] Latitude of origin
# @param max_radius [FLoat] Max radius from origin in km
# @param min_radius [FLoat] Min radius from origin in km
#
# @return [Pair<Float>] [Lng, lat] of some random point between min_radius and max_radius of origin
def random_point_within_radius_band_of_origin(lng:, lat:, max_radius:, min_radius:)
  dx, dy = random_point_in_band(min_radius, max_radius)
  random_lat = lat + dy / OneDegree
  random_lng = lng + dx / ( OneDegree * Math::cos(lat * Math::PI / 180) )
  [random_lng, random_lat]
end
0 голосов
/ 06 сентября 2018

Если вам нужен код для генерации равномерной случайной точки в радиальном диапазоне, то здесь (непроверено!)

# @param min_radius [Float] Minimum radius, in km
# @param max_radius [Float] Maximum radius, in km
#
# @return [Pair<Float>]
def random_point_in_band(min_radius, max_radius)
  r     = min_radius + (max_radius - min_radius) *  Math.sqrt(rand)
  theta = 2.0 * Math::PI * rand
  [r * Math.cos(theta), r * Math.sin(theta)]
end
...