Các đa giác riêng biệt dựa trên giao lộ bằng PostGIS


36

Tôi có một bảng đa giác PostGIS nơi một số giao nhau với nhau. Đây là những gì tôi đang cố gắng làm:

  • Đối với một đa giác đã cho được chọn bởi id, hãy cho tôi tất cả các đa giác giao nhau. Về cơ bản,select the_geom from the_table where ST_Intersects(the_geom, (select the_geom from the_table where source_id = '123'))
  • Từ các đa giác này, tôi cần tạo một đa giác mới sao cho giao điểm trở thành một đa giác mới. Vậy nếu đa giác A cắt với đa giác B, tôi sẽ nhận được 3 đa giác mới: A trừ AB, AB và B trừ AB.

Có ý kiến ​​gì không?


1
Hmmm, tôi nghĩ rằng hãy xem những gì bạn đang làm nhưng một đồ họa đơn giản có thể làm nên điều kỳ diệu giúp tôi (và những người khác) thấy chính xác những gì bạn muốn.
Jason

Đã thêm một số trong câu trả lời của tôi.
Adam Matan

Câu trả lời:


29

Vì bạn nói rằng bạn nhận được một nhóm đa giác giao nhau cho mỗi đa giác mà bạn quan tâm, bạn có thể muốn tạo cái được gọi là "lớp phủ đa giác".

Đây không phải là chính xác những gì giải pháp của Adam đang làm. Để thấy sự khác biệt, hãy xem hình ảnh về giao lộ ABC:

Giao lộ ABC

Tôi tin rằng giải pháp của Adam sẽ tạo ra một đa giác "AB" bao trùm cả khu vực "AB! C" và "ABC", cũng như một đa giác "AC" bao gồm "AC! B" và "ABC" và " Đa giác BC "đó là" BC! A "và" ABC ". Vì vậy, các đa giác đầu ra "AB", "AC" và "BC" sẽ chồng lên vùng "ABC".

Một lớp phủ đa giác tạo ra các đa giác không chồng lấp, vì vậy AB! C sẽ là một đa giác và ABC sẽ là một đa giác.

Tạo lớp phủ đa giác trong PostGIS thực sự khá đơn giản.

Về cơ bản có ba bước.

Bước 1 là trích xuất đường kẻ [Lưu ý rằng tôi đang sử dụng vòng ngoài của đa giác, sẽ phức tạp hơn một chút nếu bạn muốn xử lý chính xác các lỗ]:

SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines

Bước 2 là "nút" đường kẻ (tạo một nút tại mỗi giao lộ). Một số thư viện như JTS có các lớp "Noder" mà bạn có thể sử dụng để làm điều này, nhưng trong PostGIS, hàm ST_Union thực hiện điều đó cho bạn:

SELECT ST_Union(the_geom) AS the_geom FROM (...your lines...) AS noded_lines

Bước 3 là tạo tất cả các đa giác không chồng lấp có thể đến từ tất cả các dòng đó, được thực hiện bởi hàm ST_Polygonize :

SELECT ST_Polygonize(the_geom) AS the_geom FROM (...your noded lines...)

Bạn có thể lưu đầu ra của từng bước đó vào một bảng tạm thời hoặc bạn có thể kết hợp tất cả chúng vào một câu lệnh:

CREATE TABLE my_poly_overlay AS
SELECT geom FROM ST_Dump((
    SELECT ST_Polygonize(the_geom) AS the_geom FROM (
        SELECT ST_Union(the_geom) AS the_geom FROM (
            SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines
        ) AS noded_lines
    )
)

Tôi đang sử dụng ST_Dump vì đầu ra của ST_Polygonize là một bộ sưu tập hình học và sẽ thuận tiện hơn khi có một bảng trong đó mỗi hàng là một trong các đa giác tạo nên lớp phủ đa giác.


Lưu ý rằng ST_ExteriorRinggiảm bất kỳ lỗ. ST_Boundarysẽ bảo tồn các vòng bên trong, nhưng nó cũng sẽ tạo ra một đa giác bên trong chúng.
jpmc26

Sự kết hợp của các vòng bên ngoài sụp đổ khi có quá nhiều đa giác. Thật không may, giải pháp "đơn giản" này chỉ hoạt động đối với các trang trải nhỏ.
Pierre Racine

13

Nếu tôi hiểu chính xác, Bạn muốn lấy (A là hình học bên trái, B là bên phải):

Hình ảnh của A∪B http://img838.imageshack.us/img838/3996/intersectab1.png

Và giải nén:

A ∖ AB

Hình ảnh của A ∖ AB http://img830.imageshack.us/img830/273/intersectab2.png

AB

Hình ảnh của AB http://img828.imageshack.us/img828/7413/intersectab3.png

và B AB

Hình ảnh của B ∖ AB http://img839.imageshack.us/img839/5458/intersectab4.png

Đó là - ba hình học khác nhau cho mỗi cặp giao nhau.

Trước tiên, hãy tạo một cái nhìn của tất cả các hình học giao nhau. Giả sử tên bảng của bạn là polygons_table, chúng tôi sẽ sử dụng:

CREATE OR REPLACE VIEW p_intersections AS    -- Create a view with the 
SELECT t1.the_geom as t1_geom,               -- intersecting geoms. Each pair
       t2.the_geom as t2_geom                -- appears once (t2.id<t2.id)
    FROM polygons_table t1, polygons_table t2  
         WHERE t1.id<t2.id AND t1.the_geom && t2.the_geom 
                           AND intersects t1.the_geom, t2.the_geom;

Bây giờ chúng ta có một khung nhìn (thực tế, một bảng chỉ đọc) lưu trữ các cặp địa chất giao nhau, trong đó mỗi cặp chỉ xuất hiện một lần do t1.id<t2.idđiều kiện.

Bây giờ chúng ta hãy tập hợp nút giao thông của bạn - A∖AB, ABB∖AB, sử dụng SQL của UNIONtrên cả ba câu hỏi:

--AB:
SELECT ST_intersection(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION 

--AAB:
SELECT ST_Difference(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION

--BAB:
SELECT ST_Difference(t2.the_geom, t1.the_geom) 
    AS geom 
    FROM p_intersections;

Ghi chú:

  1. Các &&nhà điều hành được sử dụng như một bộ lọc trước khi intersectsnhà điều hành, để cải thiện hiệu suất.
  2. Tôi đã chọn tạo một VIEWthay vì một truy vấn khổng lồ; Điều này chỉ để thuận tiện.
  3. Nếu bạn có nghĩa ABlà liên minh, không phải là giao điểm, của AB- Sử dụng ST_Union thay vì st_intersection tại UNIONtruy vấn ở những nơi thích hợp.
  4. Các dấu hiệu là một dấu hiệu cho unicode Set chênh lệch; xóa nó khỏi mã nếu nó nhầm lẫn cơ sở dữ liệu của bạn.
  5. Hình ảnh lịch sự của thể loại lý thuyết Set đẹp của Wikimedia Commons .

Vé lỗi của tôi trên meta: meta.gis.stackexchange.com/questions/79/ Kẻ
Adam Matan

Giải thích tốt đẹp! Kết quả giống như trong giải pháp scw, nhưng cách của anh ta phải nhanh hơn (không tính toán / hoặc lưu trữ / giao điểm bổ sung của A và B)
stachu

Cảm ơn! Tôi nghĩ rằng tôi không lưu trữ bất kỳ thông tin bổ sung nào, vì tôi chỉ tạo SQL XEM chứ không phải bảng.
Adam Matan

Vâng, đó là sự thật, nhưng bạn tính Giao lộ bổ sung của A và B, điều này không cần thiết
stachu

5
Hình ảnh trong câu trả lời này không hoạt động nữa.
Fezter

8

Những gì bạn đang mô tả là cách mà nhà điều hành Liên minh hoạt động trong ArcGIS, nhưng nó hơi khác so với Liên minh hoặc Giao lộ trong thế giới GEOS. Hướng dẫn Shapely có các ví dụ về cách các bộ hoạt động trong GEOS . Tuy nhiên, wiki PostGIS có một ví dụ điển hình là sử dụng linework sẽ giúp bạn thực hiện thủ thuật này.

Ngoài ra, bạn có thể tính toán ba điều:

  1. ST_Intection (geom_a, geom_b)
  2. ST_Difference (geom_a, geom_b)
  3. ST_Difference (geom_b, geom_a)

Đó phải là ba đa giác bạn đã đề cập trong điểm đạn thứ hai của bạn.


2
Ví dụ wiki PostGIS là tốt
đánh dấu

ST_Intects sẽ không trả về boolean nếu chúng giao nhau hay không? Tôi nghĩ ST_Intersection sẽ hoạt động.
Jason

Vâng, lỗi đánh máy của tôi - đã được sửa trong bản gốc, cảm ơn Jason!
scw

-2

Cái gì đó như:

XÁC NHẬN VÀO GIÁ TRỊ new_table ((chọn id, the_geom từ old_table trong đó st_intersects (the_geom, (chọn the_geom từ old_table trong đó id = '123')) = true

EDIT: bạn cần giao điểm thực tế của đa giác.

XÁC NHẬN VÀO các giá trị new_table ((chọn id, ST_Intersection (the_geom, (chọn the_geom từ cũ trong đó id = 123))

xem nếu nó làm việc ra.

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.