PostGIS ST_Intection của đa giác có thể trả về các dòng


9

Khi cắt đa giác của một bảng bằng đa giác trong một bảng khác, ST_Intersection có thể trả về một tập hợp kết quả có thể được xử lý với ST_Dump. Nhiều hình học được trả về không nhất thiết phải là ST_Polygon mà còn là ST_LineString (có thể cũng là một điểm). Vì vậy, khi chạy một truy vấn

INSERT INTO c (geom)
  (SELECT (ST_Dump(ST_Intersection(a.geom,b.geom))).geom
  FROM a INNER JOIN b ON ST_Intersects(a.geom, b.geom));

khi cố gắng điền vào bảng "c" với đa giác bị cắt, nó không thành công với ERROR: Kiểu hình học (LineString) không khớp với loại cột (Đa giác)

Tôi đã thực hiện một câu lệnh CHỌN lồng nhau khác để chỉ các hình học đa giác đi qua, như:

INSERT INTO c (geom)
  (SELECT geom FROM
    (SELECT (ST_Dump(ST_Intersection(a.geom,b.geom))).geom
    FROM a INNER JOIN b ON ST_Intersects(a.geom, b.geom))) AS cl
    WHERE ST_GeometryType(cl.geom)='ST_Polygon');

Vì đây là một chút rườm rà, tôi tự hỏi liệu có một giải pháp thanh lịch hơn cho việc bỏ hình học không hợp lệ?


BTW, tôi đặt <! - ngôn ngữ: lang-sql -> trước các khối mã nhưng vẫn không có highligting. Bất kỳ gợi ý cho một noob?
Robert pendl

Để định dạng mã chỉ cần dán mã vào, chọn mã và sử dụng nút Mã mẫu {}phía trên cửa sổ chỉnh sửa Câu hỏi.
PolyGeo

Hừm, tôi đã làm điều đó, mã được đánh dấu là "mã", nhưng các từ khóa vẫn không được tô màu.
Robert pendl

Tôi thường không cố gắng làm đẹp mã SQL ở đây nhưng tôi chỉ tìm thấy một bài đăng Meta có vẻ hữu ích tại meta.stackexchange.com/questions/90521/ Lỗi - bạn đã để lại một "dòng trống giữa nhận xét và mã" chưa?
PolyGeo

Một giao điểm của hai hình học có thể mang lại bất kỳ loại hình học nào, vì vậy tôi nghĩ rằng giải pháp hiện tại của bạn là trực tiếp nhất.
Mike T

Câu trả lời:


9

Đây có thể là một điểm tốt để sử dụng chức năng ngôn ngữ SQL. Đây là một cách nhanh chóng để làm việc cho tình huống này:

CREATE OR REPLACE FUNCTION PolygonalIntersection(a geometry, b geometry)
RETURNS geometry AS $$
SELECT ST_Collect(geom)
FROM 
(SELECT (ST_Dump(ST_Intersection(a, b))).geom 
UNION ALL
-- union in an empty polygon so we get an 
-- empty geometry instead of NULL if there
-- is are no polygons in the intersection
SELECT ST_GeomFromText('POLYGON EMPTY')) SQ
WHERE ST_GeometryType(geom) = 'ST_Polygon';
$$ LANGUAGE SQL;

Điều này sẽ giữ lại các thành phần đa giác của một giao lộ, nhưng vứt bỏ mọi thứ khác. Nó luôn trả về MultiPolygon, ngay cả khi bạn có một hoặc không có thành phần.

WITH 
      square   as (SELECT ST_GeomFromText('POLYGON ((0 0, 0  1,  1  1,  1  0, 0 0))') AS geom),
biggersquare   as (SELECT ST_GeomFromText('POLYGON ((0 0, 0 10, 10 10, 10  0, 0 0))') AS geom),
adjacentsquare as (SELECT ST_GeomFromText('POLYGON ((0 0, 1  0,  1 -1, -1 -1, 0 0))') AS geom)   

SELECT ST_AsText(PolygonalIntersection(square.geom, biggersquare.geom))
  FROM square, biggersquare;
--"MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)))"

SELECT ST_AsText(PolygonalIntersection(square.geom, adjacentsquare.geom))
  FROM square, adjacentsquare;
--"MULTIPOLYGON(EMPTY)"

3

Câu trả lời rất hay từ @dbaston. Tuy nhiên, việc trả về một hình học trống thay vì null có thể gây ra vấn đề vì hình học trống được trả lại không có srid. St_Intersection cũng có thể trả về MultiPolygon. Chức năng cập nhật này thực sự hữu ích cho tôi:

CREATE OR REPLACE FUNCTION PolygonalIntersection(a geometry, b geometry)
RETURNS geometry AS $$
SELECT ST_Collect(geom)
FROM 
(SELECT (ST_Dump(ST_Intersection(a, b))).geom 
) SQ
WHERE ST_GeometryType(geom) = 'ST_Polygon' OR ST_GeometryType(geom) = 'ST_MultiPolygon';
$$ LANGUAGE SQL;
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.