Xây dựng một đa giác trên một khu vực có thể tiếp cận


10

Tôi hiện đang làm việc trong lĩnh vực isochrones và các thuật toán cơ bản. Những gì bây giờ gây ra vấn đề không phải là tính toán nếu chính isochrone, mà là trực quan hóa kết quả.
Kết quả của thuật toán isochrone của tôi là các điểm và các cạnh. Trên thực tế tôi có một giải pháp hoạt động, nhưng đối với 3873 cạnh và 1529 nút, mọi thứ dường như sẽ mất mãi mãi (khoảng 2,0 giây trên máy tính xách tay Lenovo T440s của tôi có CPU Core i7 2015 và SSD khá nhanh). Thay vì vài giây tôi muốn một cái gì đó giống như msec :-).

Có lẽ ai đó có thể giúp tôi giảm thời gian tính toán cần thiết để xây dựng các đa giác trực quan hóa các khu vực có thể tiếp cận.

Nhưng hãy đợi ... điều đầu tiên trước!
Dưới đây là một hình ảnh trực quan về các cạnh mà tôi là kết quả tính toán của isochrone của tôi: Kết quả tính toán Isochrone (bộ xương tồn tại của linestrings) Các cạnh này được lưu trữ trong bảng cơ sở dữ liệu PostGIS và là các chuỗi đơn giản.

Những gì tôi muốn hiển thị cho người dùng trông như thế này: nhập mô tả hình ảnh ở đây Lưu ý các khu vực bị ngắt kết nối ở phía nam và rất đông của hình ảnh. Chúng nên được vẽ thành các khu vực riêng biệt (vì vậy không được phép hợp nhất ở đây :-))

Hiện tại tôi đang sử dụng truy vấn này:

SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
    SELECT ST_MakePolygon(ST_ExteriorRing(ST_GeometryN(segments, generate_series(1, ST_NumGeometries(segments))))) AS polygons FROM (
        SELECT ST_Union(ST_Buffer("GEOMETRY", 20, 'quad_segs=2')) AS segments FROM my_edges AS a
    ) AS b
) AS c

Tôi đã thực hiện một số thử nghiệm và tôi cũng đã đọc rất nhiều tài liệu, nhưng tôi không thể tìm thấy một giải pháp tốt hơn.
Trong mắt tôi, vấn đề lớn là việc sử dụng ST_Union (như đã nêu trong các tài liệu, chức năng này có thể bị chậm). Điều rất thú vị là việc thay thế nó bằng ST_Collect dường như làm chậm tính toán ST_Buffer để truy vấn tất cả trong tất cả các câu hỏi sau mất nhiều thời gian hơn, mặc dù nó không lấp đầy các khu vực giữa các cạnh (nó chỉ tạo ra một vùng đệm xung quanh các dòng ):

SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
    SELECT ST_Buffer(ST_Collect(ST_LineMerge("GEOMETRY")), 20, 'quad_segs=2') AS polygons FROM my_edges AS a
) AS b

Điều này mất khoảng 3,8 giây trên hệ thống của tôi (gần gấp đôi thời gian). Kết luận đầu tiên của tôi về điểm chuẩn nhỏ này là ST_Buffer bị chậm một cách bất ngờ khi nói đến MultiLineStrings (thậm chí chậm hơn so với khi tạo bộ đệm cho mỗi dòng và hợp nhất bộ đệm - trong mắt tôi thật kỳ lạ)

Tôi cũng đã thử sử dụng các hình dạng alpha (sử dụng triển khai từ pgRouting), nhưng vì không có giá trị alpha nào để đặt (và thực tế bây giờ tôi không thực sự đặt giá trị nào để đặt giá trị như vậy) Tôi chỉ nhận được một đa giác tuyệt vời ( vì vậy tôi sẽ mất các khu vực ở phía nam và phía đông thành các khu vực riêng biệt không phải là điều tôi muốn).
Ngoài ra ST_Polygonize (đó là điều đầu tiên xuất hiện trong tâm trí tôi) không tạo ra bất kỳ kết quả có thể sử dụng nào, nhưng có lẽ tôi đã bỏ lỡ điều gì đó ở đây ...

Có cách nào tốt hơn để tạo khu vực được hiển thị trong PostGIS không? Có lẽ cũng bằng cách sử dụng mã java (jts) hoặc mã javascript phía máy khách (jsts)? Trong thực tế, tôi có thể sống với việc mất một số chi tiết miễn là các khu vực hiển thị trong kết quả của tôi được tách ra và tính toán sẽ nhanh hơn (nhiều).


Bạn có thể không chỉ sử dụng ST_Exteriorring (ST_Dump (ST_Union (ST_Buffer (geom, ....))). Bạn có thể cần kiểm tra Linestrings đôi khi xuất phát từ ST_Union sau bộ đệm, nhưng điều đó dễ dàng với ST_GeometryType (geom). Theo như sử dụng Java hoặc jsts, bạn có thể, nhưng không chắc là nhanh hơn, vì điều đó không chắc phần lớn các chức năng của Postgis (GEOS) là các cổng C / C ++ của JTS ở vị trí đầu tiên
John Powell

Bạn đã đúng, điều này hoạt động, nhưng thực tế nó không nhanh hơn (mất ~ 3,1 giây, trong khi sử dụng GeometryN mất 2 giây). Đây là những gì tôi đã sử dụng: SELECT ST_AsGeoJson (ST_Transform (ST_Exteriorring ((ST_Dump (ST_Union (ST_Buffer ("GEOMETRY", 20)))). Geom), 4326)) TỪ my_edges;
Nikolaus Krismer

@ john-barça: Ôi Tuy nhiên, điều này vẫn rất chậm (trong mắt tôi), có cách nào khác để thử không?
Nikolaus Krismer

Vấn đề thú vị .... bạn có muốn chia sẻ một số dữ liệu thử nghiệm không?
dbaston

Nếu nó giúp tôi hạnh phúc để chia sẻ một số dữ liệu. Tất cả những điều tôi làm ở đây là nguồn mở, vì vậy đây không phải là một vấn đề lớn. Điều đầu tiên cần lưu ý: Một ứng dụng web để thử nghiệm được đặt tại dbis-isochrone.uibk.ac.at:8080/testing . Thông tin thêm về những điều tôi làm việc có thể được tìm thấy tại dbis-isochrone.uibk.ac.at . Trong phần "liên kết" của trang web có một số tài liệu tham khảo thêm (bao gồm một số dữ liệu thử nghiệm)
Nikolaus Krismer

Câu trả lời:


5

Đặt tuần tự hóa GeoJSON sang một bên, việc sau mất khoảng 6,3 giây trên máy tính xách tay của tôi:

SELECT
  ST_MakePolygon(
    ST_ExteriorRing(
      (ST_Dump(
        ST_Union(
          ST_Buffer(geom, 20, 2)))).geom))
FROM bz_edges

Nhìn vào dữ liệu trong OpenJUMP, tôi nhận thấy khá nhiều chi tiết trong các đoạn phố, liên quan đến mức độ chi tiết mong muốn trong đầu ra. Dường như ngay cả việc đơn giản hóa nhanh chóng các dòng này cũng có thể tạo ra sự tăng tốc lớn trong PostGIS:

SELECT
  ST_MakePolygon(
    ST_ExteriorRing(
      (ST_Dump(
        ST_Union(
          ST_Buffer(ST_Simplify(geom, 10), 20, 2)))).geom))
FROM bz_edges

đưa mọi thứ xuống còn 2,3 giây. Tôi nghĩ rằng tôi có thể làm tốt hơn bằng cách lưu trữ hình học tổng quát trong một cột riêng biệt, thay vì tính toán nó một cách nhanh chóng, nhưng điều đó thực sự không mang lại lợi ích bổ sung nào.

Tùy thuộc vào số lượng mã bạn muốn viết, bạn gần như chắc chắn có thể làm tốt hơn trong Java, nếu không có gì khác vì bạn có thể tận dụng nhiều lõi. (Đối với giá trị của nó, JTS thực hiện thao tác trên trong 2,8 giây). Một cách tiếp cận có thể là mở rộng CascadedPolygonUnionđể làm cho một số hoạt động công đoàn xảy ra song song. (cập nhật - đây là ParallelCascadedPolygonUnion )

Tôi nhận thấy trong dữ liệu mẫu rằng các cạnh được lưu trữ với các tham chiếu đến các nút bắt đầu và kết thúc của chúng, tức là bạn có một biểu đồ dựng sẵn. Tôi nghi ngờ bạn có thể tạo ra những đa giác nhiều hơn một cách nhanh chóng nếu bạn làm việc từ biểu đồ thay vì sử dụng các hoạt động hình học chung. Ví dụ, tôi nghĩ bạn có thể như vậy:

  1. xác định các thành phần được kết nối của biểu đồ
  2. đối với mỗi thành phần được kết nối, tìm nút có tọa độ X tối thiểu (được đảm bảo ở bên ngoài thành phần)
  3. đi các cạnh của thành phần, luôn luôn rẽ trái (hoặc phải) khi có thể. Điều này sẽ cung cấp cho bạn các vòng bên ngoài của từng thành phần.
  4. đa giác vòng ngoài và đệm thích hợp.

Cảm ơn ... đơn giản hóa là một cải tiến tuyệt vời và thậm chí "đơn giản". Phải mất thời gian cần thiết trên máy tính xách tay của tôi xuống còn 1,5 giây. Nó không phải là nơi tôi muốn, nhưng tốt hơn một chút.
Nikolaus Krismer

Về giải pháp đề xuất của bạn (điểm 1-4). Âm thanh cũng rất đơn giản và đáng để thử. Tôi đã nghĩ về một cái gì đó tương tự, nhưng tôi bị mắc kẹt tại điểm1 (rất sớm :-)). Làm thế nào một người có thể xác định các thành phần được kết nối (điều duy nhất tôi có thể nghĩ đến là một truy vấn đệ quy cũng có thể rất chậm).
Nikolaus Krismer

@NikolausKrismer Tôi sử dụng cả JGraphTmáy dệt cho các nhiệm vụ như thế này. Nếu bạn viết các phương thức đồ thị của riêng bạn thay vào đó (một ý tưởng không tồi để có hiệu suất tốt nhất), một tìm kiếm chuyên sâu sẽ tìm cho bạn các thành phần. (Bạn có thể tìm thấy chúng trong PostGIS 2.2 sắp tới ST_ClusterIntersectingnhưng tôi nghĩ bạn sẽ muốn bất kỳ loại xử lý đồ thị nào xảy ra bên ngoài cơ sở dữ liệu, vì vậy điều này có thể không hữu ích).
dbaston

đây là một số gợi ý tuyệt vời Tôi đã xem JGraphT và điều này chắc chắn có thể giúp giải quyết vấn đề của tôi. Tuy nhiên, tôi cũng đã xem Postgis 2.2 và hàm ST_ClusterIntersecting -> mất khoảng 200-250msec để xác định các cụm khác nhau trong trường hợp trên. Điều đó ổn với tôi (JGraphT chắc chắn có thể làm tốt hơn). Bây giờ tôi phải đối phó với việc tạo ngoại thất (ST_Ex thầmRing không thành công, vì ST_MakePolygon nói rằng các liên kết của tôi không có vỏ)
Nikolaus Krismer 16/07/2015

Tôi thấy có hai điều phức tạp: (a) bạn không chỉ cần vòng ngoài, mà còn bất kỳ đoạn nào mở rộng ra khỏi vòng đó và (b) có vẻ như các đường của bạn không thực sự giao nhau tại một số giao lộ. Bạn sẽ cần sửa (b) nếu bạn sẽ cố gắng xây dựng một hình học từ kết quả của biểu đồ đi bộ.
dbaston
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.