2016-09-24 5 views
2

저는 postgis와 rgeo에 새로 도입되었습니다. 나는 잘못된 방식으로 문제를 해결할 수 있을지도 모릅니다. 그러나 약간의 작업을 알아내는 데 놀랐으며, 특히 &을 포함하고 있습니다. 구형 기반 객체에서는 불가능합니다.다각형 'contains'와 지원되지 않는 지오메트리에 대한 다른 연산

저는 우편 번호 같은 것을 기반으로 함께 그룹화하려는 지리적으로 분산 된 개체가 있습니다. 이 그룹들 각각에 대해 나는 경계선이 있으며, 대상물이 그 경계 안에 있는지 확인하고 한 경계가 다른 경계 안에 있는지 검사하고 싶습니다. 나는 레일을 사용하고 있는데이 지오의 역방향 조회를 현재의 경계가 구글에서 오는 내 컬렉션 모델

class CreateGeoCollectionDefinition < ActiveRecord::Migration[5.0] 
    def change 
    create_table :geo_collection_definitions do |t| 
     t.string :name 
     t.string :geo_place_id 
     t.string :geo_place_types, array: true, default: [] 
     t.st_polygon :boundary, geographic: true 
     t.jsonb :boundary_json 
     t.st_point :latlng, geographic: true 
    end 
    end 
end 

을 설정하는 데 사용 마이그레이션입니다. 북동과 남서 경계 상자 좌표는 객체 생성에이 방법으로 전달되는

GEO_FACTORY = RGeo::Geographic.spherical_factory(srid: 4326) 

def self.createBoundary(pointOne, pointTwo) 
    point1 = GEO_FACTORY.point(pointOne['lat'], pointOne['lng']) 
    point2 = GEO_FACTORY.point(pointTwo['lat'], pointTwo['lng']) 
    boundingBox = RGeo::Cartesian::BoundingBox.create_from_points(point1, point2).to_geometry 
    boundingBox 
end 

나는 모든 것이 내가 기대하는 방식으로 작동하고 확인하기 위해 사양의 일부를 작성했습니다. 간단한 거리 기반 테스트는 모두 예상대로 통과하지만 경계 기능을 테스트하는 데 사용되는 것과 관련된 문제가 있습니다. 나는 시도하고 (나는 그에게 어리석은 일을 조금 알고)

GeoCollectionDefinition.where("ST_Contains(boundary, boundary)") 

을 같은 쿼리를 실행하면 다음과 같은

# ------------------ 
# --- Caused by: --- 
# PG::UndefinedFunction: 
# ERROR: function st_contains(geography, geography) does not exist 
# LINE 1: ...COUNT(*) FROM "geo_collection_definitions" WHERE (ST_Contain... 
#                ^
# HINT: No function matches the given name and argument types. You might need to add explicit type casts. 

으로 실행하거나 내가 직접 rgeo 객체

를 사용하려고하면
it "should be possible to test is points belong in GeoCollection.boundary" do 
    factory = RGeo::Geographic.spherical_factory(srid: 4326) 
    externalPoint = factory.point(EmptyGeocodeLatLag['lng'], EmptyGeocodeLatLag['lat']) 
    expect(someplace_def.boundary.contains?(someplace_def.latlng)).to be_truthy 
    expect(someplace_def.boundary.contains?(externalPoint)).to be_falsy 
end 

내가 얻을

RGeo::Error::UnsupportedOperation: 
    Method Geometry#contains? not defined. 

보게 g 주변 나는 rgeo issue과 이러한 연산이 구형 팩토리 기반 객체에서 지원되지 않는다는 다른 증거가 있습니다.

저는 궁금합니다.

  1. 내 마이그레이션에 설명 된 경계와 방법으로 객체의 위치 나 이해가 보인다하지만 난 그것에 대해 틀렸다 추측하고있어 모델링이 확실히 경우
  2. 인가?
  3. postgis, rgeo 및 활성 레코드 어댑터를 사용하여 여러 점이 다각형 안에 있는지 알아 보려면 어떻게해야합니까?
  4. 하나의 다각형이 다른 다각형 안에 있는지 확인할 수 있습니까?

는 편집 :

나는 경사의 제안에 추적 내 DB에 직접 일부 쿼리를 실행. 첫째, 내 설정을 확인하는 것입니다.

SELECT PostGIS_full_version(); 

NOTICE: Function postgis_topology_scripts_installed() not found. Is topology support enabled and topology.sql installed?         postgis_full_version 

POSTGIS="2.1.7 r13414" GEOS="3.5.0-CAPI-1.9.0 r4084" PROJ="Rel. 4.9.2, 08 September 2015" GDAL="GDAL 1.11.5, released 2016/07/01" LIBXML="2.9.2" LIBJSON="UNKNOWN" RASTER 

일부 쿼리도 실행했습니다.

SELECT name FROM geo_collection_definitions WHERE st_contains(latlng, boundary); 
ERROR: function st_contains(geography, geography) does not exist 
LINE 1: ...ELECT name FROM geo_collection_definitions WHERE st_contain... 

그래서 추측에는 지리 정보가 포함되지 않습니다.나는 주위를 파고 성배를 발견했다.

SELECT name FROM geo_collection_definitions WHERE st_covers(boundary, latlng); 
    name 
    ------ 
    (0 rows) 

SELECT name FROM geo_collection_definitions WHERE st_covers(boundary, ST_GeomFromText('POINT(12.9549709 55.5563043)', 4326)); 
    name 
    ------ 
    (0 rows) 

이것은 latlng가 경계의 중심점이기 때문에 정말로 놀라운 일이다. 나는 꽤 혼란스럽고 나는 꽤 바보 같은 짓을하고 있다고 확신한다. 어떤 도움을 주시면 감사하겠습니다.

+1

문제는 순수 Postgis 기반으로 보이기 때문에 질문을 수정하면 도움이 될 수있다. 레일 대신 SQL 문. 내 경험에 비추어 볼 때, pure SQL로 질의를 테스트 한 후 프레임 워크에 연결하는 것이 더 나은 제어를 제공합니다. – tilt

+0

안녕 기울입니다! 답장을 보내 주셔서 감사합니다. 내가하는 바보 같은 짓이라고 확신 해. proj4가 설치되었는지 확인하려고합니다. 그런 다음 postgis db에서 직접 쿼리를 실행하여 테스트 해 보겠습니다. – Conor

+1

해당 경계의 WKT 출력을 제공 할 수 있습니까? (ST_AsText (경계)). 또한 지리 정보를 계속 사용 하시겠습니까? 대규모의 (국가 경계를 넘어선) 데이터로 작업하는 경우에는 의미가 있지만 일반적으로 로컬 프로젝션에서 작업하는 것이 좋습니다. 나는 당신의 우편 번호가 어쨌든 지리에 있다는 사실에 놀랐다. 보통은 투영 될 것이다. – tilt

답변

2

ST_DWithin을 사용하는 것이 좋습니다. 이는 PostGIS 'geography 유형에서 잘 지원됩니다. radius 매개 변수의 경우 0 또는 10을 사용할 수 있습니다 (예 : 데이터의 정확도가 10m 인 경우).

geography 유형에 ST_Contains 또는 ST_Within을 사용할 계획이 없습니다.

1

마이크와 기울기의 답변은 내가이 하단에 도착하고 당황 하나의 약간의 그러나 다만 경우에이 물건 중 하나가

ST_DWithin 확실히입니다 ... 선 아래로 다른 사람을 도울 수있는 도움 내 특별한 문제를 해결하는 길은 이것에 대해 큰소리로 외쳐야했습니다. 사양 쿼리를 이와 같이 변경했습니다.

collectionDefs = GeoCollectionDefinition.where("ST_DWithin(boundary, '#{someplace.latlng}', 10)") 
    expect(collectionDefs.count).to eq(2) 
    collectionDefs = GeoCollectionDefinition.where("ST_DWithin(boundary, 'Point(0.0 0.0)', 10)") 
    expect(collectionDefs.count).to eq(0) 

위 쿼리는 훌륭하게 실행되었지만 여전히 예상했던 결과를 얻지 못했습니다. 이것은 그 곳 길을 잘못 라운드 좌표 내가 다각형을

POLYGON((55.4965351 12.8894595,55.6445967 12.8894595,55.6445967 13.151087,55.4965351 13.151087,55.4965351 12.8894595)) and the centre point is POINT(13.0108705 55.5790534) 

을 인쇄하고 신속하게 발견 틸트의 조언에 따라 당황 비트를

입니다. 위에 설명 된 createBoundary 방법으로 피해가 발생했습니다. 나는 경계 정의 점을 만들고 lng 대신에 lat 값을 전달하고 그 반대의 경우도 마찬가지입니다. 나는 부끄러움에 머리를 걸 수 있습니다 :)

감사 만 틸트와 마이크를 다음

def self.createBoundary(pointOne, pointTwo) 
    point1 = GEO_FACTORY.point(pointOne['lng'], pointOne['lat']) 
    point2 = GEO_FACTORY.point(pointTwo['lng'], pointTwo['lat']) 
    boundingBox = RGeo::Cartesian::BoundingBox.create_from_points(point1, point2).to_geometry 
    boundingBox 
end 

에 코드를 업데이트했습니다. 나는 ST_DWithin과 프로 포스트그립트 디버깅 팁을 발견했을 텐데 절망적으로 많은 시간을 절약 해 주었다.