Как найти все полигоны, которые включают в себя специальную длинную точку широты
Я использую гем rgeo и activerecord-postgis-adapter. Я хочу найти все записи, где особая точка включена в многоугольник. Я пометил прямоугольник на карте Google и ожидаю, что sql возвращает строку, если точка находится внутри, и не возвращает строку, когда точка находится снаружи. к несчастью point_outside_2
и вернуть результат. Что я делаю не так? Должен ли я использовать проекции вместо реальных длинных лат?
describe 'polygon' do
let(:factory) { RGeo::Geographic.simple_mercator_factory }
let(:left_up_corner) { factory.point(50.095073, 19.852121) }
let(:right_up_corner) { factory.point(50.092230, 20.057740) }
let(:left_bottom_corner) { factory.point(50.021297, 19.857577) }
let(:right_bottom_corner) { factory.point(50.015820, 20.051943) }
let(:point_inside_1) { factory.point(50.059631, 19.939323) }
let(:point_inside_2) { factory.point(50.029995, 19.941997) }
let(:point_outside_1) { factory.point(50.153008, 19.990906) }
let(:point_outside_2) { factory.point(50.118037, 19.970446) }
let(:line) { factory.line_string([left_up_corner, right_up_corner, right_bottom_corner, left_bottom_corner]) }
let(:area) { factory.polygon(line) }
it 'finds nurses with polygon include point' do
Nurse.create(area: area)
expect(count_nurses(point_inside_1)).to be 1
expect(count_nurses(point_inside_2)).to be 1
expect(count_nurses(point_outside_1)).to be 0
expect(count_nurses(point_outside_2)).to be 0 # it return 1
end
def count_nurses(point)
Nurse.where("ST_DWithin(area, ST_Point(#{point.coordinates.join(',')}), 4326)").count
end
end
миграция:
class AddPolygonToNurse < ActiveRecord::Migration[5.1]
def change
add_column :nurses, :area, :st_polygon, :geographic => true
add_column :nurses, :latlong, :st_point, :geographic => true
end
end
1 ответ
Попробуйте, я делаю нечто подобное в приложении с RGeo, чтобы найти точки внутри многоугольника. Надеюсь, что это работает для вас
describe 'polygon' do
let(:factory) { RGeo::Geographic.simple_mercator_factory }
let(:ewkb_generator) do
RGeo::WKRep::WKBGenerator.new(
type_format: :ewkb,
emit_ewkb_srid: true,
hex_format: true
)
end
let(:left_up_corner) { factory.point(50.095073, 19.852121) }
let(:right_up_corner) { factory.point(50.092230, 20.057740) }
let(:left_bottom_corner) { factory.point(50.021297, 19.857577) }
let(:right_bottom_corner) { factory.point(50.015820, 20.051943) }
let(:point_inside_1) { factory.point(50.059631, 19.939323) }
let(:point_inside_2) { factory.point(50.029995, 19.941997) }
let(:point_outside_1) { factory.point(50.153008, 19.990906) }
let(:point_outside_2) { factory.point(50.118037, 19.970446) }
let(:line) { factory.line_string([left_up_corner, right_up_corner, right_bottom_corner, left_bottom_corner]) }
let(:area) { factory.polygon(line) }
it 'finds nurses with polygon include point' do
Nurse.create(area: area)
expect(count_nurses(point_inside_1)).to be 1
expect(count_nurses(point_inside_2)).to be 1
expect(count_nurses(point_outside_1)).to be 0
expect(count_nurses(point_outside_2)).to be 0 # it return 1
end
def count_nurses(point)
ewkb = ewkb_generator.generate(point.projection)
Nurse.where('ST_Intersects(area, ST_GeomFromEWKB(E?))', "\\\\x#{ewkb}").count
end
end