Tối ưu hóa một tính toán hàng xóm gần nhất bằng PostGIS


13

Tôi đang sử dụng PostGIS để tính toán các đa giác lân cận gần nhất. Điều tôi muốn tính toán là khoảng cách tối thiểu từ mỗi đa giác, đến đa giác gần nhất.

Cho đến nay tôi đã nhận được sự giúp đỡ rất lớn từ câu trả lời của Mike Toews (mà tôi trích dẫn bằng một thay đổi nhỏ) ở đây:

SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_Distance(a.the_geom, b.the_geom) AS distance_between_a_and_b
FROM 
  public."TestArea" AS a, public."TestArea" AS b
WHERE
  a.hgt !=  b.hgt AND ST_Distance(a.the_geom, b.the_geom) < 400

Sau đó, tôi tính tối thiểu:

SELECT a_hgt, MIN(distance_between_a_and_b)
FROM public."lon_TestArea"
GROUP BY a_hgt

Tuy nhiên, thách thức của tôi là tính toán điều này cho một số lượng lớn đa giác (1.000.000). Vì phép tính trên so sánh từng đa giác với mọi đa giác khác, tôi tự hỏi làm thế nào tôi có thể cải thiện phép tính để tôi không phải thực hiện 10 ^ 12 phép tính.

Một suy nghĩ tôi đã có là đệm từng đa giác, và sau đó tính toán các lân cận gần nhất của tất cả các giá trị trong bộ đệm cho đa giác đó và ghi lại mức tối thiểu. Tôi không chắc đó là cách tiếp cận tốt nhất hay liệu có chức năng nào trong PostGIS mà tôi nên sử dụng hay không.


EDIT: Sử dụng một trong những gợi ý của Nicklas, tôi đang thử nghiệm ST_Dwithin():

CREATE TABLE mytable_withinRange AS SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_DWithin(a.the_geom, b.the_geom, 400)
FROM 
  public."lon_TestArea" AS a, public."lon_TestArea" AS b

nhập mô tả hình ảnh ở đây

Điều này trả về một bảng ID của mỗi đa giác, và liệu nó có nằm trong một khoảng cách nhất định hay không. Có thể xây dựng một IF/ELSEcâu lệnh kiểu bằng SQL không? (Tôi đã đọc về việc sử dụng CASEđiều kiện) Hoặc tôi có nên thử tham gia bảng tôi sản xuất vào bảng gốc và sau đó chạy lại truy vấn bằng ST_Distance không?


hãy xem ví dụ thứ hai trong liên kết boston gis trong câu trả lời của tôi. bạn nên sử dụng st_dwithin trong phần truy vấn.
Nicklas Avén

Câu trả lời:


7

Có một phần "Hàng xóm gần nhất" trên trang BostonGIS .


BIÊN TẬP:

Làm thế nào về

CREATE TABLE mytable_withinRange AS SELECT 
 a.hgt AS a_hgt,
 b.hgt AS b_hgt
FROM 
 public."lon_TestArea" AS a, public."lon_TestArea" AS b
WHERE 
 ST_DWithin(a.the_geom, b.the_geom, 400)

Liên quan đến tuyên bố CASE :

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;

Bạn có biết nếu dòng WHERE ST_DWithin(a.the_geom, b.the_geom, 400)sẽ ngăn khoảng cách lớn hơn sau đó 400được tính toán hoặc chỉ được ghi lại? Ngoài ra, một tuyên bố trường hợp có thể được sử dụng để tính toán số? ví dụ:CASE WHEN ST_DWithin(a.the_geom, b.the_geom, 400) == TRUE THEN ST_DWithin(a.the_geom, b.the_geom)
djq

1
@celenius Nếu khoảng cách hơn 400 m, không có gì trong phần chọn sẽ được tính. Tôi không hiểu lý do tại sao bạn muốn đặt trường hợp vào hỗn hợp.
Nicklas Avén

@Nicklas ok - Tôi hiểu. Tôi nghĩ rằng nó có thể có nghĩa là chỉ khoảng cách ít hơn 400 được lưu trữ; điều này làm cho nó dễ dàng hơn nhiều so với tôi mặc dù. Cảm ơn!
djq

3

Ê

Có một số điều được xem xét để làm cho mọi thứ di chuyển nhanh hơn, và một số điều có thể có thể trong tương lai.

Đầu tiên , bạn đề cập rằng bạn đang xem xét sử dụng bộ đệm để tìm đa giác trong một phạm vi tối thiểu để tránh tính toán tất cả các kết hợp.

Như đã thảo luận trong một liên kết khác từ Boston, đây là cách đúng đắn để làm điều đó trong PostGIS là sử dụng ST_Dwithin . ST_Dwithin sử dụng chỉ mục để tìm hàng xóm trong một phạm vi nhất định.

Tất nhiên, nó phụ thuộc vào tập dữ liệu nếu chỉ sử dụng một giá trị cố định cho st_DWithin cho tất cả các đa giác hoặc nếu bạn cần làm gì đó như underdark và wildintellect đang thảo luận.

Điều thứ hai là sử dụng PostGIS 1.5+ tại đây. Đó là bởi vì tính toán đa giác với đa giác nhanh hơn nhiều kể từ 1,5 nếu các hộp giới hạn của chúng không giao nhau. Bạn có thể đọc thêm về điều đó ở đây. .

Điều thứ ba cần đề cập là tương lai.

Trong PostgreSQL 9.1 sẽ có một thứ gọi là knn-gist. Đó là một chỉ mục không thể chỉ trả lời có hay không mà còn trả về kết quả được đặt hàng trực tiếp từ chỉ mục. Bạn có thể đọc về điều đó ở đây .

Nhưng vẫn sẽ có rất nhiều việc phải làm ở phía PostGIS trước khi ý chính sẽ giúp cho những việc như thế này. Có một vé cho điều đó ở đây.

Trân trọng

Nicklas


Cảm ơn những lời đề nghị Nicklas; vì tôi thấy khó khăn khi tải pgAdmin / PostGIS và chạy, tôi nghĩ rằng tôi sẽ tránh sử dụng 1.5 vào lúc này. Có vẻ như ST_Dwithin () là một cách để giải quyết điều này.
djq

2
cài đặt 1.5 sẽ không ảnh hưởng đến mối quan hệ giữa postgresql và pgadmin. bạn có thể có nhiều hơn một phiên bản của postgis trong máy chủ cơ sở dữ liệu và sau đó bạn tải một trong số chúng trong cơ sở dữ liệu. vì vậy bạn có thể có một cơ sở dữ liệu 1.4 và một 1.5 cho cùng một máy chủ cơ sở dữ liệu.
Nicklas Avén

1

Các trang tiếp theo liên quan đến công việc bậc thầy của Nathan Kerr cung cấp một số hiểu biết tốt về vấn đề trực tiếp này. Đồng nghiệp của tôi đã thử phương pháp Bostongis ở đâyđây , nhưng có một số vấn đề khiến nó hoạt động tốt.

Một cách tiếp cận khác để suy nghĩ về điều tương tự như bộ đệm là thực hiện một hình chữ nhật mở rộng / hợp đồng. Về cơ bản vượt qua 1 làm một hộp giới hạn (đó là một đơn vị + x thẳng đến hộp đa giác ban đầu của bạn) giao nhau mà bạn nghĩ sẽ bắt được ít nhất một giao điểm. Đối với dữ liệu có giao điểm thực hiện một truy vấn phụ kiểm tra các kết quả khớp đó gần nhất. Đối với dữ liệu không khớp, mở rộng hộp giới hạn và lặp lại.

Đây rõ ràng là một vấn đề lập trình đệ quy và có thể được thực hiện tốt hơn trong Python với Shapely hơn 100% trực tiếp trong postgis.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.