Tìm đa giác đầu nguồn


8

Đây là một câu hỏi tiếp theo cho câu hỏi này .

Tôi có một mạng lưới sông (multiline) và một số đa giác thoát nước (xem hình dưới đây). Mục tiêu của tôi là chỉ chọn các đa giác đầu nguồn (màu xanh lá cây).

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

Với giải pháp của John, tôi có thể dễ dàng trích xuất các điểm bắt đầu của dòng sông (sao). Tuy nhiên, tôi có thể có các tình huống (đa giác màu đỏ) trong đó tôi có điểm bắt đầu trong một đa giác, nhưng đa giác không phải là đa giác đầu nguồn, bởi vì nó được bay qua sông. Tôi chỉ muốn các đa giác đầu nguồn.

Tôi đã cố gắng chọn chúng bằng cách đếm số lượng giao điểm giữa đa giác và sông (lý do: một đa giác đầu nguồn chỉ có 1 giao điểm với sông)

SELECT 
    polyg.*
FROM 
    polyg, start_points, stream
WHERE 
    st_contains(polyg.geom, start_points.geom)
    AND ST_Npoints(ST_Intersection(poly.geom, stream.geom)) = 1

, trong đó poylg là poylgons, start_point từ câu trả lời của johns và luồng là mạng lưới sông của tôi.

Tuy nhiên, điều này mất mãi mãi và tôi đã không chạy nó:

"Nested Loop  (cost=0.00..20547115.26 rows=641247 width=3075)"
"  Join Filter: _st_contains(ezg.geom, start_points.geom)"
"  ->  Nested Loop  (cost=0.00..20264906.12 rows=327276 width=3075)"
"        Join Filter: (st_npoints(st_intersection(ezg.geom, rivers.geom)) = 1)"
"        ->  Seq Scan on ezg_2500km2_31467 ezg  (cost=0.00..2161.52 rows=1648 width=3075)"
"              Filter: ((st_area(geom) / 1000000::double precision) < 100::double precision)"
"        ->  Materialize  (cost=0.00..6364.77 rows=39718 width=318)"
"              ->  Seq Scan on stream_typ rivers  (cost=0.00..4498.18 rows=39718 width=318)"
"  ->  Index Scan using idx_river_starts on river_starts start_points  (cost=0.00..0.60 rows=1 width=32)"
"        Index Cond: (ezg.geom && geom)"

Vì vậy, câu hỏi của tôi là: Làm thế nào tôi có thể truy vấn đa giác nước đầu một cách hiệu quả?

Cập nhật: Tôi đã thêm một số dữ liệu mẫu vào dropbox của mình . Dữ liệu là từ phía tây nam nước Đức. Đó là hai tệp hình dạng - một có luồng và một có đa giác.


Vì vậy, chỉ cần rõ ràng, bạn muốn các đa giác chỉ chứa điểm bắt đầu, không phải điểm bắt đầu. Và các điểm bắt đầu được xác định như trong câu hỏi trước của bạn (mà tôi đã trả lời, và theo như tôi biết), chính xác?
John Powell

Jupp, chỉ các đa giác có chứa điểm bắt đầu VÀ không được đi qua một con sông / chỉ là điểm bắt đầu của dòng sông. Đa giác màu đỏ ở trên chứa các điểm bắt đầu, nhưng KHÔNG phải là đa giác đầu nguồn khi dòng sông chảy qua / không bắt đầu trong đa giác ...
EDi

Vì vậy, bạn muốn tập hợp polygonschỉ chứa những điểm đó là nguồn sông (từ câu hỏi trước) và loại trừ bất kỳ nơi nào hai con sông gặp nhau. Xin lỗi, cho tất cả các câu hỏi, chỉ muốn chắc chắn.
John Powell

Không, ví dụ trong đa giác xanh thấp hơn, hai con sông gặp nhau. Tôi muốn loại trừ những người polygonscó một dòng sông đi qua (dòng sông chảy vào và rời khỏi đa giác) và giữ những người bắt đầu (và những dòng sông chỉ để lại đa giác này).
EDi

1
Tôi không biết bất kỳ PostGIS nào, vì vậy tôi không thể giúp với mã trực tiếp, tuy nhiên, trong ArcGIS, tôi sẽ đi theo các dòng sau: (1) giao nhau giữa các dòng và đa giác thành một tệp điểm. (2) xóa (không gian) điểm giống hệt nhau. (3) thêm một trường số vào tham số điểm với giá trị 1 cho mỗi điểm. (4) không gian nối đa giác vào các điểm và sử dụng tổng của trường số để chỉ ra loại thoát nước. Tổng bằng 1 có nghĩa là nó là một địa đầu. Cao hơn 1 có nghĩa là có nhiều hơn 1 lối vào hoặc lối ra.
Mikkel Lydholm Rasmussen

Câu trả lời:


4

Tôi tin rằng phác thảo chung (một phần đã được thử nghiệm cho đến nay) là:

  1. Tìm các điểm đại diện cho các nguồn luồng, như trong câu trả lời này .

  2. Giao với bảng đa giác để lấy số đỉnh nguồn theo đa giác.

  3. Sử dụng ST_DumpPoints kết hợp với nhóm theo hình học để có được số lượng từng điểm. Ý tưởng là có được số lượng bao nhiêu con sông gặp nhau tại một điểm nhất định.

Một ví dụ về truy vấn như vậy:

SELECT count(geom), ST_AsText(geom) as wkt
FROM 
   (SELECT (ST_DumpPoints(foo.geom)).geom 
   FROM 
     (SELECT 
        ST_Collect(ST_MakeLine(ST_MakePoint(0,0), ST_MakePoint(10,10)),
                   ST_MakeLine(ST_MakePoint(0,0), ST_MakePoint(20,20))
        ) as geom
     ) foo 
 ) bar 
 GROUP BY geom; 

Trả về:

count  |  wkt      
-------+--------------
 2     | POINT(0 0)
 1     | POINT(10 10)
 1     | POINT(20 20)
  1. Chạy một giao điểm 3so với bảng đa giác, để có được số đếm (tổng số đỉnh) của các điểm nối sông trên mỗi đa giác.

  2. Tham gia đa giác từ 2trên 4, từ chối những điểm có tổng số (tổng số đỉnh) của điểm tại một điểm nối lớn hơn tổng của các nguồn sông, thu được bằng cách tính tổng các nguồn theo đa giác từ bước 1 và 2. Nếu điều kiện này giữ, nó sẽ giữ có nghĩa là ít nhất một trong số các con sông gặp nhau tại một ngã ba, có nguồn gốc bên ngoài đa giác trong câu hỏi.

Tất cả những thứ này có thể được kết hợp với nhau trong một chuỗi các CTE, trừ khi một số bảng được tạo từ các bước liên quan đến các điểm (và được lập chỉ mục).

Tôi không biết thời gian chạy của cái này sẽ là gì trên một tập dữ liệu đầy đủ, chỉ thử nghiệm một phần của cái này trên một tập hợp con, nhưng với chỉ số không gian trên bảng đa giác, sẽ có một số trợ giúp - rõ ràng là không thể áp dụng một chỉ mục cho các điểm xuất hiện từ ST_DumpPoints, do đó, cần phải quét toàn bộ ở đó, mặc dù lúc đó chúng sẽ nằm trong bộ nhớ.

Đây không phải là một câu trả lời đầy đủ , mà là một công việc đang tiến triển, và một cơ hội để tìm ra lỗ hổng trong logic. Sắp có truy vấn.

CHỈNH SỬA 1

Đây là truy vấn tôi đã đưa ra, dường như hoạt động trên một tập hợp con dữ liệu nhỏ của bạn, nhưng chạy hàng giờ trên bộ dữ liệu đầy đủ.

CREATE TABLE good_polys as  
   WITH 
     rivers as 
       (SELECT (ST_DUMP(ST_LineMerge(geom))).geom as geom FROM streams),
     start_points as
       (SELECT ST_StartPoint(geom) as geom FROM rivers),
     end_points as 
        (SELECT ST_EndPoint(geom) as geom FROM rivers),
     junctions as 
        (SELECT (ST_DumpPoints(geom)).geom 
        FROM (SELECT geom FROM streams) s),
     source_polygons as 
        (SELECT 
            count(rivers.geom) as source_count, 
            polygons.geom, 
            polygons.gid 
         FROM rivers, polygons
         WHERE st_intersects(polygons.geom, rivers.geom) 
         GROUP BY polygons.geom, polygons.gid),
     junction_polygons as 
        (SELECT 
            count(junctions.geom) as junction_count, 
            polygons.geom, 
            polygons.gid 
         FROM junctions, polygons
         WHERE st_intersects(polygons.geom, junctions.geom) 
         GROUP BY polygons.geom, polygons.gid)
    SELECT 
       jp.gid 
    FROM 
       junction_polygons jp, source_polygons sp 
    WHERE ST_Equals(jp.geom, sp.geom) 
    AND junction_count <= source_count;

CHỈNH SỬA 2 . Mặc dù điều này dường như tạo ra câu trả lời chính xác trên một tập hợp con nhỏ, thời gian chạy trên bộ dữ liệu đầy đủ là khủng khiếp , có lẽ là do truy vấn cuối cùng đang thực hiện n ^ 2 so sánh và không sử dụng chỉ mục không gian. Giải pháp có thể là phá vỡ truy vấn và tạo các bảng từ các điểm ban đầu và điểm trong các truy vấn đa giác, sau đó có thể được lập chỉ mục không gian trước bước cuối cùng.


Truy vấn hiện đang chạy trên máy tính để bàn của tôi. Tôi không biết sẽ mất bao lâu hoặc liệu nó có chính xác hay không, mặc dù nó có vẻ hợp lý từ một mẫu nhỏ dữ liệu của bạn. Bạn có biết bao nhiêu đa giác đáp ứng tiêu chí của bạn không?
John Powell

Tôi sẽ chạy truy vấn trên một máy chủ. Tôi nghĩ rằng chỉ một phần nhỏ của đa giác sẽ đáp ứng các tiêu chí lựa chọn ...
EDi

Đó là những gì tôi tìm thấy trên một tập hợp con. Tôi sẽ đăng câu hỏi của mình sau khi kết thúc
John Powell

Đơn giản hóa vào ngày mai.
John Powell

Xin lỗi, hôm nay rất bận. Tôi nghĩ rằng câu trả lời là chạy truy vấn nguồn và các nút giao tiếp sông trước, giao với bảng đa giác để lấy số lượng trên mỗi đa giác, lưu chúng dưới dạng bảng và sau đó lập chỉ mục cho chúng. Sau đó chạy bước cuối cùng, trong đó hình học bằng nhau và so sánh số điểm từ hai bảng. Tôi hy vọng điều này sau đó sẽ sử dụng một chỉ mục thay vì thực hiện so sánh n² như hiện tại. Sẽ đăng lại sau.
John Powell

0

Trong mã giả, điều này sẽ hoạt động:

  • chọn tất cả từ đa giác
  • (FULL OUTER?) Tham gia với các điểm trên đa giác cắt nhau các điểm
  • (FULL OUTER?) Tham gia các dòng trong đó đa giác cắt các dòng
  • là line.riverid không bằng point.riverid
  • nhóm theo đa giác
  • đếm (điểm)> 0

Tôi không thực sự chắc chắn làm thế nào để xây dựng truy vấn và tôi không thể kiểm tra nó mà không có cơ sở dữ liệu để kiểm tra. Đó là một truy vấn khá điên rồ, tôi nghĩ vậy. Nhưng nó nên hoạt động!

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.