สร้างบัฟเฟอร์ที่ละลายจากหลายเรขาคณิต (รวมกันโดยแอตทริบิวต์ที่ใช้ร่วมกันและการแยกเชิงพื้นที่)


10

ฉันจะสร้างบัฟเฟอร์ที่ละลายจากคุณสมบัติอินพุตหลายจุด ในตัวอย่างด้านล่างตารางอินพุตมี 4 ฟีเจอร์ คุณลักษณะ#2ประกอบด้วยรูปทรงเรขาคณิตสองจุด หลังจากสร้างบัฟเฟอร์ฉันได้รับรูปเรขาคณิต 4 เหลี่ยม:

ป้อนคำอธิบายรูปภาพที่นี่

มีวิธีการจัดกลุ่มผลลัพธ์หรือไม่ บัฟเฟอร์ของจุด#1และ#2ถูกยุบและควรเป็นคุณลักษณะหลายรูปหลายเหลี่ยม ( a)

สิ่งที่ฉันทำไปแล้ว:

-- 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;

แก้ไข:

-- 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));

คุณใช้แบบสอบถามย่อยมากเกินไป สิ่งนี้จะลดความสามารถของคุณในการจัดกลุ่มตามบนแอตทริบิวต์ที่คุณต้องการทำคลัสเตอร์
Vince

ดังนั้นคุณต้องทำการรวมกันของอวกาศแล้วรวมกันเป็นยูเนี่ยนตามหมายเลขคุณลักษณะซึ่งเป็นสาเหตุที่คุณคาดหวัง 3 มัลติโพลิกอนจากแผนภาพด้านบน ฉันสงสัยว่าสิ่งนี้จะต้องใช้กระบวนการสองขั้นตอน แต่ต้องการชัดเจนในคำถามก่อนเสนอคำตอบ
John Powell

ใช่ฉันต้องการรวมรูปหลายเหลี่ยมบัฟเฟอร์และรวบรวมผลลัพธ์ตามจำนวนของคุณลักษณะการป้อนข้อมูล
eclipsed_by_the_moon

มีการอัพเดทอะไรบ้าง? ฉันต้องการทราบว่าสิ่งนี้ใช้ได้ผลกับคุณเท่าที่ฉันเห็นหรือไม่ฉันได้ตอบคำถามแล้ว
John Powell

ขออภัยสำหรับการตอบกลับช้าฉันไม่ได้ออนไลน์สองสามวัน
eclipsed_by_the_moon

คำตอบ:


7

เริ่มต้นด้วยการสุ่มคะแนนในการพยายามเลียนแบบในภาพของ OP ที่จุดตัดสองจุดแรกจากนั้นจุดที่สองและสามจะมี id แอตทริบิวต์เดียวกัน (2) โดยมีจุดอื่น ๆ สองจุดที่ไม่มีจุดตัด คุณลักษณะเดียวกันแบบสอบถามต่อไปนี้สร้าง 3 คลัสเตอร์:

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;

มีหลายขั้นตอนที่นี่:

  1. ใช้ST_Union, จัดกลุ่มตาม id, ไปยังกลุ่มแรกโดยแอตทริบิวต์
  2. ใช้ST_ClusterIntersectingเพื่อรวมสิ่งเหล่านั้นจากกลุ่มเดียวกันที่ตัดกันเชิงพื้นที่
  3. เพิ่ม id ให้กับแต่ละกลุ่ม (multis ตาราง) - พยายามทำสิ่งนี้โดยตรงใน ClusterIntersecting นำไปสู่รูปทรงเรขาคณิตทั้งหมดที่ได้รับรหัส 1
  4. รวมรูปทรงเรขาคณิตที่ทิ้งแล้วจากขั้นตอนที่ 2 โดยจัดกลุ่มตามรหัสจากขั้นตอนที่ 3 - นี่คือส่วนที่ละลาย สิ่งนี้ทำให้รูปหลายเหลี่ยมที่ซ้อนกันสองอันในคลัสเตอร์ A ของคุณเข้าร่วมด้วยกันแทนที่จะเป็นรูปแบบซ้อนทับกันเนื่องจากอยู่ตอนท้ายของขั้นตอนที่ 2

ค่อนข้างยาว แต่ใช้งานได้ (และฉันแน่ใจว่ามีวิธีที่สั้นกว่า)

การใช้เครื่องมือ WKT ใน QGIS (และค้นพบว่าฉันน่ากลัวเพียงใดกับเครื่องมือแก้ไข) สร้างกลุ่มดังต่อไปนี้ซึ่งคุณสามารถเห็นกลุ่มของคุณที่มีข้อความว่า a มีอยู่ด้วยกัน - คือสีเดียว

ป้อนคำอธิบายรูปภาพที่นี่

หากคุณใส่ข้อความ ST_AsText แบบสุดท้าย ST_UNION (d.geom) คุณจะเห็นผลลัพธ์ได้โดยตรง

แก้ไขตามข้อมูลเพิ่มเติมในความคิดเห็น:ในขณะที่คุณเริ่มต้นด้วยคะแนนคุณจะต้องรวมบัฟเฟอร์ในโซลูชันดั้งเดิมของฉัน - ซึ่งฉันใส่ CTE ชั่วคราวที่จุดเริ่มต้นเพื่อเลียนแบบไดอะแกรมของคุณ มันจะง่ายกว่าในการเพิ่มบัฟเฟอร์ใน CTE ของสหภาพเพื่อให้คุณสามารถทำรูปทรงเรขาคณิตทั้งหมดในครั้งเดียว ตัวอย่างเช่นการใช้บัฟเฟอร์ระยะทาง 1,000 ตัวอย่างต่อไปนี้จะส่งคืน 3 คลัสเตอร์ตามที่คาดไว้

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;

ขออภัยมันใช้เวลานานมากในการติดต่อกลับหาคุณ ฉันมีปัญหาในการมองเห็นรูปทรงบัฟเฟอร์ใน QGIS ผมได้พยายามที่จะปรับเปลี่ยนแบบสอบถามของคุณโดยใช้ST_SetSRID, ST_Multiและ::geometry(Multipolygon, /*SRID*/), แต่ในขณะที่มันไม่ทำงาน
eclipsed_by_the_moon

ตกลงถ้าคุณสามารถโพสต์รหัสของคุณและปรับปรุงข้อมูลให้ดีขึ้นฉันอาจช่วยได้
John Powell

ฉันได้เพิ่ม SQL เพื่อสร้างจุดตัวอย่าง
eclipsed_by_the_moon

บิตผูกขึ้นวันนี้ฉันจะย้อนกลับโดยเร็วที่สุด จะต้องทำงานแบบหลายจุดในแบบสอบถามด้วย
John Powell

3

วิธีหนึ่งในการทำเช่นนี้คือST_Unionการบัฟเฟอร์ทั้งหมดเข้าด้วยกันST_Dumpผลลัพธ์ที่ได้รับส่วนประกอบของรูปหลายเหลี่ยมที่เกิดขึ้นและเข้าร่วมกับST_Intersectsกลับไปที่จุดอินพุตเพื่อค้นหาจำนวน / จุดที่ประกอบกันเป็นกลุ่ม

ซึ่งสามารถทำได้โดยไม่ต้องเข้าร่วมโดยการจัดกลุ่มจุดด้วยกันก่อนที่จะST_Bufferเรียก epsสำหรับสองจุดที่จะตั้งอยู่ภายในบัฟเฟอร์ละลายเดียวกันพวกเขาจะต้องสามารถเข้าถึงได้โดยการกระโดดระหว่างจุดของระยะทางน้อยกว่า นี่เป็นเพียงปัญหาการเชื่อมโยงขั้นต่ำซึ่งสามารถแก้ไขได้โดยใช้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;

โปรดทราบว่าสิ่งนี้จะไม่ให้ผลลัพธ์ที่เหมือนกันกับวิธีการบัฟเฟอร์แรกเนื่องจากบัฟเฟอร์ PostGIS ไม่ใช่วงกลมที่สมบูรณ์แบบและจุดสองจุดห่างกัน 1,000 เมตรอาจไม่ได้เชื่อมต่อกันด้วยบัฟเฟอร์ 500m สองตัว


ดูเหมือนว่าเรามีความคิดที่คล้ายกัน ฉันยังไม่ได้ทดสอบของคุณ แต่ฉันแน่ใจว่ามันใช้งานได้และสะอาดกว่าของฉัน
John Powell

ดูเหมือนว่า PostGIS 2.2.1 ไม่รองรับ ST_ClusterDBSCAN ฉันได้ติดตั้ง PostGIS 2.3.2 แล้ว แต่ส่วนขยาย postgis ใหม่ใน pgAdmin ยังคงเป็นรุ่น 2.2.1
eclipsed_by_the_moon

0

ตามคำตอบนี้คุณต้องการทำ ST_DUMP ในแบบสอบถามย่อยของคุณ

บางสิ่งเช่นนี้

-- 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;

สาเหตุที่ST_UNIONส่งคืนมัลติโพลิกอนที่ละลายของคุณสมบัติทั้งหมดและST_DUMPแยกสิ่งนี้ออกเป็นคุณสมบัติรูปหลายเหลี่ยมแต่ละอัน (ซึ่งถูกละลาย)


1
วิธีนี้ใช้ไม่ได้เนื่องจากแอตทริบิวต์ใด ๆ ที่จำเป็นในการทำคลัสเตอร์รูปหลายเหลี่ยมหลายส่วนที่ต้องการจะสูญหายไป
Vince

ฉันได้ลองST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geomแล้ว แต่นี่เป็นการสร้าง 4 คุณสมบัติแทน 3
eclipsed_by_the_moon

โอ้ใช่คุณต้องการจัดกลุ่มตามหมายเลขหรือไม่ คุณจะต้องก่อนที่คุณจะGROUP_BY ST_UNION
Alex Leith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.