Tạo khảm như Biểu đồ Voronoi từ các đa giác rời rạc


12

Hình minh họa dưới đây cho thấy vấn đề :

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

như trong (a) Tôi có một tập hợp các đa giác rời rạc, như hình học trong PostGIS. Tôi cần một cái gì đó như (b) , "khảm" của tập hợp đa giác này, xây dựng nó theo tiêu chí "vùng ảnh hưởng" ... Giống như một công trình Voronoi (minh họa bởi (c) ): trên thực tế, nếu đa giác là điểm, các khu vực ảnh hưởng là Voronoi.

Tóm tắt: Tôi cần một thuật toán SQL (hoặc một số cụ thể cho PostGIS) để tạo ra "khảm" của một tập hợp các đa giác rời rạc. (có lẽ là một vòng lặp của các hoạt động ST_Buffer và ST_Difference nhỏ)

PS: Tôi cần, giống như của Voronoi, việc phân định không gian (khung bình phương trong (b) ) bị bỏ qua.


Vấn đề này tương tự như vấn đề khác về dòng .

EDIT (sau khi bình luận @FelixIP)

Tôi muốn ở lại trong vũ trụ vectơ , để không bị mất độ chính xác (ví dụ: sử dụng ST_DelaunayTriangles và thêm và trừ nội thất bằng các đa giác ban đầu, chúng điều chỉnh một giải pháp đồ thị kép ) ... Một số gói đơn giản và tự động như pprepair (được hỗ trợ như các công cụ tôpô của QGIS không tự động). Nhưng raster có lẽ đơn giản hơn và ít tiêu tốn CPU hơn.

Hình minh họa "quá trình GRID" này cũng có giá trị như một giải pháp, giả sử rằng nó có thể cho phép độ chính xác tương tự và "vùng ảnh hưởng của hạt nhân phát triển".

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

Trong ARCGIS tồn tại một công cụ phân tích không gian được gọi là Phân bổ Euclide , vì vậy, có lẽ có một giải pháp tương tự PostGIS , bắt đầu bằng tập hợp các đa giác (phân loại, rasterizing và tạo lại các đa giác).


Cảm ơn @Nir, xin lỗi sự nhầm lẫn với các điểm, tôi không sử dụng điểm, chỉ đa giác là các mục (a)(b) của hình minh họa ... Bạn có liên kết về đầu mối của mình về giải pháp không?
Peter Krauss

Trong arcgis có một giải pháp raster gọi là phân bổ hoặc vùng lân cận
FelixIP

Cảm ơn @FelixIP, tôi đã chỉnh sửa thành "giải pháp raster tốt" ;-)
Peter Krauss

Nếu bạn xóa đa giác của mình khỏi phạm vi của chúng.aspolygon, bạn sẽ bị bỏ lại với đa giác. Bộ xương của nó gis.stackexchange.com/questions/177/ mài là những gì bạn cần tôi đoán. Việc thực hiện là một vấn đề lớn
FelixIP

1
@Cyril, tôi có thể xem lại kịch bản của bạn ... Tuần tới. Đăng một cái gì đó có vẻ là một giải pháp với các chức năng PostGIS hiện đại, sẽ là bước đầu tiên tốt.
Peter Krauss

Câu trả lời:


1

Vì vậy, tôi sẽ chuẩn bị một chiếc bánh cho bạn - đĩa trái cây, sử dụng các công cụ PostGis, như bạn yêu cầu, nếu tôi hiểu chính xác câu hỏi và như tôi đã đề cập, trách nhiệm đối với hoạt động của lò PostGIS do đội ngũ sáng tạo của cô ấy chịu.

Tôi sẽ yêu cầu không bị xúc phạm bởi bất cứ ai theo phong cách hài hước của tôi và hiểu nó như một trò chơi!

Tệp gốc là trái cây thái lát và hình dạng đơn giản (sau đây gọi là trái cây), xem Hình 1 bên dưới.

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

Đây là công thức của tôi, và tôi sẽ được giúp đỡ bởi những lập trình viên thân yêu, người mà bạn sẽ tìm hiểu sau này. Hãy bắt đầu, và để làm điều này, chúng tôi sẽ tạo ra một loại bột trong đó trái cây của chúng tôi sẽ được đặt, để chạy kịch bản:

create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;

Xem kết quả trong Hình 2 bên dưới

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

Bây giờ, nếu có ít trái cây, như trong hình của tôi, hãy tạo đường viền của bộ đệm ngoài trên trái cây hoặc nếu có nhiều trái cây, hãy tạo đường viền của bộ đệm âm, để chạy tập lệnh:

create table poly_buff_dump as SELECT ((ST_Dump(ST_Boundary(ST_Union(ST_Buffer((geom),0.01, 'join=mitre mitre_limit=5.0'))))).geom) geom FROM poly;

Và cắt các đường đệm xung quanh mỗi quả

UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true; Xem kết quả trong Hình 3 bên dưới

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

(Trên thực tế, tôi đã nghĩ rằng kết quả là tôi sẽ nhận được các đường gãy (chẳng hạn như trong một vòng tròn), nhưng nếu các số liệu khó khăn, đôi khi phá vỡ được, ví dụ, một bên của hình chữ nhật rơi ra, v.v. )

Sau đó, bạn cần chia các dòng thu được một cách thuận tiện cho bạn thành các phân đoạn bằng nhau và trích xuất các điểm từ chúng

create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;

Kết quả, xem Hình 4 bên dưới

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

Bây giờ hãy chạy công cụ Voronoi, ở nơi này tôi đã sử dụng công cụ được đề xuất bởi liên kết MickyT: /gis//a/172246/120129 , do đó bạn sẽ tạo các bảng có tên là voronoi Vì thực tế, người trợ lý đầu tiên của tôi là tách biệt với đầu bếp nhờ đầu bếp! :-).

Cách thứ hai trong bước này là chạy hàm ST_VoronoiPolygons.

Kết quả, xem Hình 5 bên dưới

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

Bây giờ, cắt bỏ các phần bổ sung bằng cách chạy tập lệnh:

create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom); Kết quả, xem Hình 6 bên dưới.

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

Bây giờ hãy chạy tập lệnh để căn chỉnh kiểu geodata trong LineString:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; Và bây giờ tôi sẽ yêu cầu "người bạn đời thứ hai của tôi" nhận nhiệm vụ của mình và trộn bánh chào mừng (Jeff - /gis//a/785/120129 ), san bằng nó trong một lớp duy nhất và cho điều đó , cảm ơn tôi cho nó!

CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) ); Bây giờ là lúc để tôi đi làm, nơi tôi chạy kịch bản:

create table poly_voronoi_union as SELECT b.id, (ST_ConvexHull(ST_Union(a.geom, b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects(a.geom, b.geom) GROUP BY b.id, a.geom, b.geom; và một kịch bản khác:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; xem hình 7 bên dưới

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

Như bạn có thể thấy trong hình, các vết cắt của chúng tôi có các lớp nhỏ, có thể được loại bỏ, như một tùy chọn sử dụng ST_SnapToGrid (hoặc theo cách khác):

Và cuối cùng, chúng tôi sẽ cắt trái cây nướng ra khỏi chiếc bánh của mình, tôi thậm chí còn hơi mệt khi đứng cạnh lò nướng, :-)

create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom); Kết quả xem hình 8 nhập mô tả hình ảnh ở đây

Tất cả mọi thứ từ ngày này, bây giờ mọi người sẽ học cách nướng bánh nướng ngon - đĩa trái cây. Giúp mình tất cả, và chọn những mảnh bạn, thích cho tất cả mọi người.

(Thật đáng tiếc khi tôi thực sự không thể nuôi tất cả mọi người, không phải bằng bánh điện tử, nhưng với bánh thật, có lẽ cơn đói sẽ chấm dứt trên Trái đất ...)

Chỉnh sửa: Anh đào trên chiếc bánh có thể trông như thế này :-):

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM poly),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT ST_Intersection(a.geom, b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects(a.geom,b.geom)),
tbld AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM poly GROUP BY id, geom)
SELECT id, ST_Union(a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

hoặc là

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM polygons),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

Với bạn là Mr.Baker tốt và công bằng, cảm ơn tất cả và chúc may mắn ,: -) ...

Giải pháp ban đầu.

Kịch bản này được gọi là: ST_VoronoiDiagramsFromPolygons.


1
Xin chào, minh họa tốt, và có vẻ như kết quả tốt (!). Gợi ý cho một cuộc thảo luận ngắn gọn, xem giải pháp @geogeek, các bước trong QGis dường như là các bước chính của PostGIS tại đây ... Tại sao e cần ST_BufferST_ConvexHull? Có một thuật toán thay thế?
Peter Krauss

1) Xem, ST_Buffer và trên đa giác được tạo để giảm các đường phân tách giữa các số liệu ban đầu trong khi áp dụng hàm Voronoi, do đó, kích thước bộ đệm bạn có thể chỉ định càng lớn, các đường phân tách sẽ càng được xây dựng càng trơn tru một hàm Voronoi ... 2) ST_ConvexHull từ vô số hình trên mỗi đa giác, đa giác chúng ta cần ... 3) Hôm nay, đây là tầm nhìn của tôi trong việc giải quyết câu hỏi của bạn, tôi không biết điều gì sẽ xảy ra với tất cả chúng ta và các quyết định của chúng tôi trong tương lai ...
Cyril M

Một giá trị quan trọng khác của các dòng đệm là chúng sẽ giúp chúng ta chọn các đoạn từ kết quả của chức năng của Voronoi để tạo đa giác kết hợp cho mỗi hình dạng ...
Cyril M

Nhân tiện, tôi hoan nghênh việc cải tiến mã và cách tiếp cận, để chúng không làm xấu đi kết quả ...
Cyril M

1
Xin chào Cyril, tôi đồng ý rằng ST_Buffer là một lựa chọn tốt để bình thường hóa các đường viền, hoàn hảo (!). Giới thiệu ST_ConvexHull, chỉ là một sự tò mò, loại kết quả nào chúng ta có thể thu được sau Hình 6, poly_voronoi_unionmà không có ST_ConvexHull.
Peter Krauss

8

Postgis không có chức năng chuyên dụng cho voronoi, nhưng Qgis chứa chức năng vornoi có thể tạo đa giác voronoi từ các điểm, vì vậy sử dụng qgis tôi đã làm theo các bước sau để có kết quả sau:

-make điểm từ đa giác bằng cách sử dụng extract nodeschức năng.

-make đa giác vornoi bằng cách sử dụng các hàm voroi trong Qgis.

- thực hiện một tham gia không gian trong Qgis.

-kết quả giải quyết.

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


1
Giải pháp tốt đẹp (!), Và cảm ơn minh họa. Bạn có thể tăng cường nó? Xem hình chữ nhật bên trái bên dưới, nó có 4 điểm tại Voronoi và trung tâm của hình chữ nhật không có biểu tượng, làm biến dạng vùng của nó (mất hình tam giác) ... Có lẽ việc tăng cường có thể lấy mẫu thường xuyên của mỗi đa giác ... và có lẽ cũng có một số điểm nội thất.
Peter Krauss

Tôi sử dụng công cụ tăng cường trong ArcGIS. Điều này cải thiện đáng kể đa giác gần. +1
FelixIP

3

OK - Nghĩ về điều này một chút và thấy nó giống như một cái gì đó tôi đã xem xét gần đây.

Hãy bắt đầu các polys:

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

Tạo một thuộc tính mới với một số (100 trong trường hợp của tôi) Sử dụng Vector-> Công cụ nghiên cứu -> Điểm ngẫu nhiên trong công cụ đa giác, điều này sẽ tạo ra (100) điểm bên trong mỗi đa giác: nhập mô tả hình ảnh ở đây

Sau đó, Vector-> Công cụ hình học -> Voronoi để tạo các polys dựa trên lớp điểm đó.

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

Bây giờ, bạn có thể sử dụng công cụ Vector -> Truy vấn không gian: Chọn các điểm thuộc về một đa giác (hoặc một trong các đa giác) Sử dụng công cụ truy vấn không gian để tạo một lựa chọn đa giác voronoi của bạn áp dụng cho đa giác đó. Thêm một thuộc tính cho đa giác voroni tương ứng với đa giác quan tâm. (Tôi mới sử dụng 1,2,3,4)

Bây giờ bạn có thể Vector-> Công cụ xử lý địa lý-> hòa tan dựa trên thuộc tính mới của bạn.

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


Cảm ơn @AAmes (!), Hình minh họa rất tốt và phương pháp này là một lựa chọn tốt ... Nhưng câu hỏi là về "thuật toán SQL (hoặc một số cụ thể cho PostGIS)" và bây giờ, tiền thưởng về việc sử dụng hàm ST_VoronoiPolygons () , có lẽ giải quyết tất cả vấn đề chỉ bằng một cú nhấp chuột ;-)
Peter Krauss

@AAmes Một tìm kiếm nhanh cho thấy rằng phương pháp này thực sự có thể được sử dụng trong PostGIS. Làm thế nào để tạo các điểm ngẫu nhiên trong một đa giác trong postgis giải thích việc tạo điểm từ đa giác và từ đó nó sẽ khá thẳng về phía trước.
Phil G

Tiền thưởng của tôi là dành cho bạn, như một sự khích lệ (chào mừng bạn đến đây!), Nhưng TRẢ LỜI NÀY LÀ CÔNG VIỆC cho các yêu cầu về câu hỏi và tiền thưởng.
Peter Krauss

Cảm ơn Peter, tôi đã thấy ghi chú của bạn nhưng tiếc là tôi không có cơ hội quay lại và giải quyết nó. Tôi chưa có bất kỳ kinh nghiệm nào về PostGIS và điều đó sẽ khiến tôi mất nhiều thời gian hơn tôi có thể đưa ra bất kỳ phản hồi tốt nào. Tôi hy vọng rằng việc khám phá không gian này của chúng tôi sẽ hữu ích cho mọi người trong tương lai, có lẽ nếu tôi sớm nhận được một vết nứt tại PostGIS, tôi sẽ quay lại và thực hiện một cú đánh khác vào đó để thực hành!
AA

2

Điểm ngẫu nhiên là một ý tưởng tốt để tạo đa giác voronoi từ đa giác, nó hoạt động khá tốt, nhưng thật tệ khi các đa giác gần nhau: nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

ST_ApproximateMedialAxis là một lựa chọn tốt khác nếu sử dụng PostGIS: Tính toán biểu đồ Voronoi cho đa giác

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.