Tạo bộ đệm hòa tan từ đa hình học (Liên kết theo thuộc tính chia sẻ và giao điểm không gian)


10

Tôi đã tạo bộ đệm hòa tan từ các tính năng đầu vào đa điểm. Trong ví dụ dưới đây, bảng đầu vào chứa 4 tính năng. Tính năng #2bao gồm hai hình học điểm. Sau khi tạo bộ đệm, tôi nhận được 4 hình học đa giác:

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

Có cách nào để nhóm kết quả? Bộ đệm của các điểm #1#2được hòa tan và phải là một tính năng đa giác đơn ( a).

Những gì tôi đã làm cho đến nay:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/) AS geom
FROM
public.multipoints)
AS sub_qry;

BIÊN TẬP:

-- create sample geometries

CREATE TABLE public.multipoints (
gid serial NOT NULL,
geom geometry(MultiPoint, 31256),
CONSTRAINT multipoints_pkey PRIMARY KEY (gid)
);

CREATE INDEX sidx_multipoints_geom
ON public.multipoints
USING gist
(geom);

INSERT INTO public.multipoints (gid, geom) VALUES
(1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),
(2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),
(3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
(4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256));

Bạn sử dụng các truy vấn con quá nhiều. Điều này giúp loại bỏ khả năng NHÓM THEO của bạn trên thuộc tính mà bạn muốn phân cụm.
Vince

Vì vậy, bạn cần phải thực hiện một liên minh không gian và sau đó là một liên minh dựa trên số tính năng, đó là lý do tại sao bạn mong đợi 3 đa dữ liệu từ sơ đồ trên. Tôi nghi ngờ điều này sẽ đòi hỏi một quá trình hai bước, nhưng chỉ muốn rõ ràng về câu hỏi, trước khi đưa ra câu trả lời.
John Powell

Có, tôi muốn hợp nhất các đa giác bộ đệm và thu thập kết quả dựa trên số lượng các tính năng đầu vào.
lu

Bất kỳ cập nhật về điều này? Tôi muốn biết nếu điều này làm việc cho bạn, như tôi có thể thấy, tôi đã trả lời câu hỏi.
John Powell

Xin lỗi vì đã trả lời trễ, tôi đã không trực tuyến trong một vài ngày.
lu

Câu trả lời:


7

Bắt đầu với một số điểm ngẫu nhiên, trong một nhận thức bắt chước những điểm trong hình ảnh của OP, trong đó hai điểm đầu tiên giao nhau về mặt không gian, sau đó điểm thứ 2 và thứ 3 có cùng thuộc tính id (2), với một vài điểm khác không giao nhau về mặt không gian và không có cùng thuộc tính, truy vấn sau đây tạo ra 3 cụm:

WITH 
  temp (id, geom) AS 
     (VALUES (1, ST_Buffer(ST_Makepoint(0, 0), 2)),
        (2, ST_Buffer(ST_MakePoint(-0.7,0.5), 2)),
        (2, ST_Buffer(ST_MakePoint(10, 10), 2)), 
        (3, ST_Buffer(ST_MakePoint(-2, 12), 2)), 
        (4, ST_Buffer(ST_MakePoint(5, -6), 2))),
 unions(geoms) AS 
      (SELECT ST_Union(geom) FROM temp GROUP BY id),
 clusters(geoms) AS 
      (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
         FROM unions),
 multis(id, geoms) AS 
      (SELECT row_number() over() as id, geoms FROM clusters)
 SELECT ST_UNION(d.geom) FROM 
      (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Có một số bước ở đây:

  1. sử dụng ST_Union, nhóm theo id, để nhóm đầu tiên theo thuộc tính
  2. sử dụng ST_ClusterIntersectingđể kết hợp những người từ cùng một nhóm giao nhau trong không gian
  3. thêm một id vào mỗi cụm (bảng multis) - cố gắng thực hiện điều này trực tiếp trong ClusterIntersecting dẫn đến tất cả các hình học nhận được id là 1
  4. Liên kết các hình học bị đổ từ bước 2, nhóm theo id từ bước 3 - đây là phần hòa tan . Điều này làm cho hai đa giác chồng chéo trong cụm A của bạn, được nối với nhau, thay vì chồng chéo, vì chúng ở cuối bước 2.

Khá dài, nhưng nó hoạt động (và, tôi chắc chắn có một cách ngắn hơn).

Sử dụng công cụ WKT trong QGIS, (và khám phá mức độ khủng khiếp của tôi với các công cụ chỉnh sửa) tạo ra các cụm như sau, trong đó bạn có thể thấy cụm được gắn nhãn là a, hoàn toàn cùng nhau - tức là một màu.

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

Nếu bạn đặt ST_AsText vào vòng chung kết, ST_UNION (d.geom), thì bạn có thể xem kết quả trực tiếp.

EDIT theo dõi thêm thông tin trong các bình luận: Khi bạn bắt đầu với các điểm, bạn sẽ cần kết hợp bộ đệm vào giải pháp ban đầu của tôi - mà tôi đã đưa vào CTE tạm thời khi bắt đầu mô phỏng sơ đồ của bạn. Sẽ dễ dàng hơn để thêm bộ đệm trong các hiệp hội CTE, vì vậy bạn có thể thực hiện tất cả các hình học cùng một lúc. Vì vậy, sử dụng khoảng cách bộ đệm là 1000, làm ví dụ, sau đây trả về 3 cụm, như mong đợi.

WITH temp(id, geom) AS 
  (VALUES 
      (1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),   
      (2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),                                                
      (3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
      (4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256))
),                                              
unions(geoms) AS 
  (SELECT st_buffer(ST_Union(geom), 1000) FROM temp GROUP BY id),
clusters(geoms) AS 
  (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
     FROM unions),
multis(id, geoms) AS 
  (SELECT row_number() over() as id, geoms FROM clusters)
SELECT id, ST_UNION(d.geom) FROM 
  (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Xin lỗi phải mất rất lâu để trở lại với bạn. Tôi có một số rắc rối để hình dung các hình học đệm trong QGIS. Tôi đã cố gắng để thay đổi truy vấn của bạn sử dụng ST_SetSRID, ST_Multi::geometry(Multipolygon, /*SRID*/), nhưng vào lúc này nó không làm việc.
lu mờ_by_the_moon

OK, nếu bạn có thể đăng mã của mình và thậm chí tốt hơn một số dữ liệu, tôi có thể giúp bạn.
John Powell

Tôi đã thêm một số SQL để tạo các điểm mẫu.
lu mờ_by_the_moon

Bit bị trói ngày hôm nay, tôi sẽ hoàn nguyên ngay khi tôi có thể. Sẽ phải làm việc đa điểm vào truy vấn quá.
John Powell

3

Một cách để làm điều này là kết hợp ST_Uniontất cả các bộ đệm với nhau, ST_Dumpkết quả để có được các thành phần của đa giác kết quả và nối ST_Intersectslại với các điểm đầu vào để tìm ra có bao nhiêu / điểm tạo thành mỗi cụm.

Điều này có thể được thực hiện mà không yêu cầu tham gia bằng cách nhóm các điểm lại với nhau trước khi gọi ST_Buffer. Để hai điểm được đặt trong cùng một bộ đệm hòa tan, chúng phải có thể truy cập được bằng các bước nhảy giữa các điểm có khoảng cách nhỏ hơn eps. Đây chỉ là một vấn đề phân cụm liên kết tối thiểu, có thể được giải quyết bằng cách sử dụng ST_ClusterDBSCAN:

SELECT
  cluster_id,
  ST_Union(ST_Buffer(geom, 1000)) AS geom,
  count(*)                        AS num_points,
  array_agg(point_id)             AS point_ids
FROM (
  SELECT
    point_id,
    ST_ClusterDBSCAN(geom, eps := 2000, minpoints := 1) OVER() AS cluster_id ,
    geom
  FROM points) sq
 GROUP BY cluster_id;

Lưu ý rằng điều này sẽ không tạo ra kết quả chính xác như phương pháp đệm đầu tiên, bởi vì bộ đệm PostGIS không phải là vòng tròn hoàn hảo và hai điểm cách nhau 1000m có thể không được kết nối bởi hai bộ đệm 500m.


Có vẻ như chúng tôi đã có một ý tưởng tương tự. Tôi đã không kiểm tra của bạn, nhưng tôi chắc chắn rằng nó hoạt động, và sạch sẽ hơn của tôi.
John Powell

Có vẻ như PostGIS 2.2.1 không hỗ trợ ST_ClusterDBSCAN. Tôi đã cài đặt PostGIS 2.3.2, nhưng các tiện ích mở rộng postgis mới trong pgAdmin vẫn là phiên bản 2.2.1.
lu mờ_by_the_moon

0

Theo câu trả lời này, bạn muốn thực hiện ST_DUMP trong truy vấn con của mình.

Một cái gì đó như thế này:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/)) AS geom
FROM
public.multipoints)
AS sub_qry;

Lý do tại sao điều đó ST_UNIONtrả về một đa giác hòa tan của tất cả các tính năng và ST_DUMPphá vỡ điều này thành các tính năng đa giác riêng lẻ (đã bị hòa tan).


1
Điều này sẽ không thực sự hoạt động, bởi vì bất kỳ thuộc tính nào cần thiết để phân cụm đa giác nhiều phần mong muốn sẽ bị mất.
Vince

Tôi đã thử ST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geom, nhưng điều này tạo ra 4 tính năng thay vì 3.
eclipsed_by_the_moon

Oh, phải, bạn muốn nhóm theo số? Bạn sẽ cần GROUP_BYtrước bạn ST_UNION.
Alex Leith
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.