Cách nhanh nhất để tham gia một cách không gian CSV với đa giác Shapefile


19

Tôi có tệp CSV 1 tỷ điểm và một shapefile với khoảng 5.000 đa giác. Điều gì sẽ là cách nhanh nhất để tham gia không gian điểm và đa giác? Đối với mỗi điểm, tôi cần lấy id đa giác chứa. (Đa giác không trùng nhau.)

Thông thường, tôi sẽ tải cả hai tập dữ liệu vào PostGIS. Có cách nào nhanh hơn để hoàn thành công việc không?

Tôi đang tìm kiếm một giải pháp nguồn mở.

Câu trả lời:


16

Nếu "nhanh nhất" bao gồm lượng thời gian bạn sử dụng, giải pháp sẽ phụ thuộc vào phần mềm bạn cảm thấy thoải mái và có thể sử dụng nhanh chóng. Do đó, các nhận xét sau đây tập trung vào các ý tưởng để đạt được thời gian tính toán nhanh nhất có thể .

Nếu bạn sử dụng chương trình đóng hộp, gần như chắc chắn điều tốt nhất bạn có thể làm là xử lý trước các đa giác để thiết lập cấu trúc dữ liệu đa giác điểm, như cây KD hoặc tứ giác, có hiệu suất thường là O (log (V (V) ) * (N + V)) trong đó V là tổng số đỉnh trong đa giác và N là số điểm, vì cấu trúc dữ liệu sẽ mất ít nhất nỗ lực O (log (V) * V) để tạo và sau đó sẽ phải được thăm dò cho mỗi điểm với chi phí mỗi điểm O (log (V)).

Bạn có thể làm tốt hơn đáng kể bằng cách đầu tiên chia lưới cho các đa giác, khai thác giả định không có sự chồng chéo. Mỗi ô lưới hoàn toàn nằm trong một đa giác bên trong (bao gồm cả phần bên trong của "đa giác phổ quát"), trong trường hợp này gắn nhãn ô với id của đa giác, hoặc nếu không nó chứa một hoặc nhiều cạnh đa giác. Chi phí của quá trình rasterization này, bằng với số lượng ô lưới được tham chiếu trong khi raster hóa tất cả các cạnh, là O (V / c) trong đó c là kích thước của một ô, nhưng hằng số ẩn trong ký hiệu big-O là nhỏ.

(Một điểm hay của phương pháp này là bạn có thể khai thác các thói quen đồ họa tiêu chuẩn. Ví dụ: nếu bạn có một hệ thống (a) sẽ vẽ các đa giác trên màn hình ảo bằng cách sử dụng (b) một màu riêng biệt cho mỗi đa giác và (c) cho phép bạn đọc màu của bất kỳ pixel nào bạn quan tâm để giải quyết, bạn đã thực hiện nó.)

Khi có lưới này, sàng lọc trước các điểm bằng cách tính toán ô chứa mỗi điểm (thao tác O (1) chỉ cần một vài đồng hồ). Trừ khi các điểm được nhóm xung quanh các ranh giới đa giác, điều này thường sẽ chỉ để lại các điểm O (c) với kết quả không rõ ràng. Do đó, tổng chi phí xây dựng lưới và sàng lọc trước là O (V / c + 1 / c ^ 2) + O (N). Bạn phải sử dụng một số phương pháp khác (chẳng hạn như bất kỳ phương pháp nào được đề xuất cho đến nay) để xử lý các điểm còn lại (nghĩa là các điểm gần với ranh giới đa giác), với chi phí là O (log (V) * N * c) .

Khi c càng nhỏ, càng ít điểm sẽ nằm trong cùng một ô lưới có cạnh và do đó càng ngày càng ít sẽ yêu cầu xử lý O (log (V)) tiếp theo. Hành động chống lại điều này là cần phải lưu trữ các ô lưới O (1 / c ^ 2) và dành thời gian O (V / c + 1 / c ^ 2) để quét các đa giác. Do đó sẽ có một kích thước lưới tối ưu c. Sử dụng nó, tổng chi phí tính toán là O (log (V) * N) nhưng hằng ngầm thường là cách nhỏ hơn so với sử dụng các thủ tục đóng hộp, do O (N) tốc độ của pre-sàng lọc.

Cách đây 20 năm, tôi đã thử nghiệm phương pháp này (sử dụng các điểm cách đều nhau trên khắp nước Anh và ngoài khơi và khai thác một mạng lưới tương đối thô với khoảng 400 nghìn tế bào được cung cấp bởi bộ đệm video thời đó) và đạt được hai mức tăng tốc độ so với thuật toán được công bố tốt nhất tôi có thể tìm thấy. Ngay cả khi các đa giác nhỏ và đơn giản (như hình tam giác), bạn hầu như chắc chắn về một thứ tự tăng tốc độ.

Theo kinh nghiệm của tôi, việc tính toán nhanh đến mức toàn bộ hoạt động bị giới hạn bởi tốc độ I / O dữ liệu chứ không phải bởi CPU. Dự đoán rằng I / O có thể là nút cổ chai, bạn sẽ đạt được kết quả nhanh nhất bằng cách lưu trữ các điểm dưới dạng nén nhất có thể để giảm thiểu thời gian đọc dữ liệu. Cũng đưa ra một số suy nghĩ về cách lưu trữ kết quả, để bạn có thể hạn chế ghi đĩa.


6
Điểm rất tốt về thời gian dành cho việc hiện thực hóa giải pháp so với thời gian tính toán. Mất một thời gian dài để đi đến một giải pháp tối ưu chỉ có lợi nếu bạn nhận ra những khoản tiết kiệm đó thông qua việc tối ưu hóa (đặc biệt theo quan điểm của nhà tuyển dụng).
Sasa Ivetic

5

Về phần tôi, tôi có thể sẽ tải dữ liệu CSV vào một tệp shp và sau đó viết một tập lệnh python bằng cách sử dụng shapefile và tạo hình để lấy id đa giác chứa và cập nhật giá trị trường.

Tôi không biết liệu geotools và JTS có nhanh hơn shapefile / shapely không ... Không có thời gian để kiểm tra nó!

chỉnh sửa : Nhân tiện , việc chuyển đổi csv sang định dạng shapefile có thể không bắt buộc, vì các giá trị có thể dễ dàng được định dạng để được kiểm tra với các đối tượng không gian từ shapefile đa giác của bạn.


4
Tôi sẽ trực tiếp tải dữ liệu bằng trình đọc csv và điền vào chỉ mục không gian Rtree . Sự kết hợp giữa Rtree và Shapely có hiệu suất ấn tượng (tốt hơn nhiều so với PostGIS; tôi không thể so sánh với JTS vì tôi không biết Java).
Mike T

2
Ý tưởng tốt miễn là bạn không cần lưu trữ tất cả 1b điểm trong bộ nhớ cùng một lúc. Tối thiểu 16 byte mỗi điểm (X / Y), bạn đang xem dữ liệu trị giá 16 GB. Nếu Rtree sẽ xây dựng chỉ mục trên bộ nhớ cục bộ, thì nó chắc chắn sẽ cải thiện hiệu suất. Nhập 1b điểm vào một shapefile sẽ không hoạt động. Thông số kỹ thuật OGR shapefiles được giới hạn ở 8GB (khuyến nghị 4GB). Một hình dạng điểm duy nhất sử dụng 20 byte.
Sasa Ivetic

4

Cuối cùng tôi đã chuyển đổi các đa giác thành một raster và lấy mẫu tại các vị trí điểm. Vì đa giác của tôi không trùng lặp và độ chính xác cao là không cần thiết (đa giác đại diện cho các lớp sử dụng đất và đường viền của chúng được coi là không chắc chắn) dù sao đây cũng là giải pháp hiệu quả nhất mà tôi có thể đưa ra.


3

Tôi sẽ nhanh chóng viết một chương trình java nhỏ dựa trên đọc shapefile của GeoTools và hoạt động chứa của JTS . Tôi không biết nó có thể nhanh đến mức nào ...


1
Nếu bạn có dữ liệu trong PostGIS thì GeoTools có thể sử dụng các chỉ mục chính, v.v.
Ian Turton

3

Sử dụng Spatialite .

Tải xuống GUI. Bạn có thể mở cả Shapefile và CSV dưới dạng bảng ảo. Điều này có nghĩa là bạn không thực sự nhập chúng vào cơ sở dữ liệu nhưng chúng xuất hiện dưới dạng bảng và bạn có thể nhanh chóng tham gia và truy vấn chúng theo bất kỳ cách nào bạn muốn.


3

Bạn có thể làm điều đó khá nhanh bằng cách sử dụng OGR trong C / C ++ / Python (Python phải là chậm nhất trong 3). Lặp qua tất cả các đa giác và đặt bộ lọc vào các điểm, lặp qua các điểm được lọc và bạn sẽ biết rằng mỗi điểm mà bạn lặp qua sẽ thuộc về đa giác hiện tại. Đây là mã mẫu trong python sử dụng OGR sẽ lặp qua các đa giác và các điểm lọc tương ứng. Mã C / C ++ sẽ trông khá giống với mã này và tôi sẽ tưởng tượng bạn sẽ tăng tốc độ đáng kể so với python. Bạn sẽ phải thêm một vài dòng mã để cập nhật CSV khi bạn thực hiện:

from osgeo import ogr
from osgeo.gdalconst import *

inPolyDS = ogr.Open("winnipeg.shp", GA_ReadOnly)
inPolyLayer = inPolyDS.GetLayer(0)
inPointDS = ogr.Open("busstops.vrt", GA_ReadOnly)   
inPointLayer = inPointDS.GetLayerByName("busstops")

inPolyFeat = inPolyLayer.GetNextFeature()
while inPolyFeat is not None:
  inPtFeat = inPointLayer.GetNextFeature()
  while inPtFeat is not None:
    ptGeom = inPtFeat.GetGeometryRef()
    # Do work here...

    inPtFeat = inPointLayer.GetNextFeature()

  inPolyFeat = inPolyLayer.GetNextFeature()

Tệp VRT (busstops.vrt):

<OGRVRTDataSource>
  <OGRVRTLayer name="busstops">
    <SrcDataSource>busstops.csv</SrcDataSource>
    <GeometryType>wkbPoint</GeometryType>
    <LayerSRS>WGS84</LayerSRS>
    <GeometryField encoding="PointFromColumns" x="X" y="Y" reportSrcColumn="FALSE" />
  </OGRVRTLayer>
</OGRVRTDataSource>

Tệp CSV (busstops.csv):

FID,X,Y,stop_name
1,-97.1394781371062,49.8712241633646,Southbound Osborne at Mulvey

Tệp CSVT (busstops.csvt, OGR cần nó để xác định các loại cột, nếu không nó sẽ không thực hiện bộ lọc không gian):

Integer,Real,Real,String

2
Không phải vòng lặp qua 1 tỷ điểm 5000 lần (một lần cho mỗi đa giác) sao?
underdark

Một chỉ số không gian là phải tuyệt đối . Tôi đã đề cập đến Rtree trước đây và tôi sẽ nhắc lại lần nữa!
Mike T

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.