Chuyển đổi Centroid Feature Centroid thành Points bằng Python


9

Tôi muốn chuyển đổi một số tệp shp dựa trên đa giác có một số tính năng đa giác thành các điểm cho mỗi tính năng về cơ bản sẽ đại diện cho tâm của mỗi tính năng đa giác. Tôi biết trong thế giới ArcGIS tôi có thể sử dụng công cụ Feature To Point nhưng tôi muốn giữ điều này trong một tập lệnh có thể chạy trên PC mà không có sự hấp dẫn đối với họ vì vậy tôi đang tìm kiếm một giải pháp thay thế nguồn mở cho điều đó. Có ai biết về một thư viện mà tôi có thể sử dụng cho việc này cùng với một số hướng về cách tận dụng nó để thực hiện việc này không?


Tôi vẫn đang gặp nhiều vấn đề với câu trả lời mà Gene cung cấp dưới đây. Vấn đề là làm thế nào nó sắp xếp lại các thuộc tính từ thứ tự ban đầu của chúng thành bảng chữ cái vốn là một vấn đề. Thứ hai, tệp hình dạng bị hỏng có thể do tệp tôi đang cố gắng chuyển đổi có hơn 250 thuộc tính.
wilbev

Có một công cụ tiêu chuẩn được gọi là 'Polygon Centroids' trong QGIS thực hiện chính xác điều này - bạn có yêu cầu một tập lệnh không? Tôi nghĩ nó sẽ đủ dễ để sử dụng PyQGIS.
Dùn Caan

Nó cần phải là một tập lệnh và hoạt động trên PC không có QGIS trên chúng.
wilbev

Câu trả lời:


9

Bạn có thể chạy một ogr2ogrlệnh (ví dụ từ Shell OSGeo4w). Ví dụ: trên một shapefile của các quốc gia:

cd path/to/shapefiles
ogr2ogr -sql "SELECT ST_Centroid(geometry), * FROM countries" -dialect sqlite countries_centroid.shp countries.shp

Shapefile mới countries_centroid.shpphải tương tự như đầu vào, nhưng chỉ chứa một điểm trên Đa giác [Đa].

@PEL cũng cho thấy một ví dụ hay với ST_PointOnSurface, rất đơn giản để thay thế trong lệnh này.


Một cái gì đó tương tự có thể được thực hiện trong Python, nếu cần, nhưng nó có thể mất thêm một vài dòng mã:

import os
from osgeo import ogr

ogr.UseExceptions()
os.chdir('path/to/shapefiles')

ds = ogr.Open('countries.shp')
ly = ds.ExecuteSQL('SELECT ST_Centroid(geometry), * FROM countries', dialect='sqlite')
drv = ogr.GetDriverByName('Esri shapefile')
ds2 = drv.CreateDataSource('countries_centroid.shp')
ds2.CopyLayer(ly, '')
ly = ds = ds2 = None  # save, close

Tôi nghĩ bạn đã đề xuất và giải pháp đơn giản nhất với OGR và SQL. Tôi nghĩ sẽ an toàn hơn khi thêm một tham số vào OGR với -nlt Point
PEL

Thật không may, tôi không thể làm điều này để làm việc. Tôi gặp lỗi khi cho rằng ST_Centroid không hoạt động.
wilbev

1
Nó cần tùy chọn phương ngữ SQLite (như được hiển thị) và Spatialite được tích hợp trong GDAL, không phải lúc nào cũng được đảm bảo. OSGeo4W có phiên bản GDAL tốt sẽ chạy lệnh này một cách chính xác.
Mike T

Tôi có thể nhận được tập lệnh hàng đầu của bạn trong ogr2ogr khen ngợi để làm việc mà không có vấn đề. Tuy nhiên, tôi cần thực hiện điều này trong một tập lệnh python độc lập vì vậy tôi đang cố gắng để bộ mã thứ 2 của bạn hoạt động, đó là nơi tôi tiếp tục với ST_Centroid không phải là lỗi chức năng. Mã của tôi giống hệt với những gì bạn có ở trên bao gồm cả phương ngữ sqlite.
wilbev

1
Lỗi bạn mô tả là khi GDAL được xây dựng mà không có hỗ trợ Spatialite. Một số gói gdal-python hỗ trợ này, nhưng không phải tất cả. Hãy thử mở một vỏ OSGeo4W và chạy tập lệnh Python từ môi trường đó. Tôi nghĩ rằng các gói mặc định liên quan để gdal-binbao gồm hỗ trợ này.
Mike T

9

Chỉ cần sử dụng Fiona hoặc GeoPandas (Python 2.7.x và 3.x)

Một số đa giác

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

import geopandas as gpd
# GeoDataFrame creation
poly = gpd.read_file("geoch_poly.shp")
poly.head()

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

Chuyển đổi thành điểm (centroid)

# copy poly to new GeoDataFrame
points = poly.copy()
# change the geometry
points.geometry = points['geometry'].centroid
# same crs
points.crs =poly.crs
points.head()

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

# save the shapefile
points.to_file('geoch_centroid.shp')

Kết quả

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


Cảm ơn gen trả lời. Tôi nghĩ rằng bạn có thể có một lỗi đánh máy ở trên, nơi biến 'gdf' phải là 'poly "phải không? Trong mã points.crs = gdf.crs. Tôi cũng gặp một số vấn đề khác khi tệp .prj không nhận được được tạo, nó hiển thị trống và thứ tự của các trường thuộc tính đang thay đổi thứ tự của chúng từ dữ liệu đa giác vì dường như chúng được sắp xếp theo thứ tự chữ cái. Điều quan trọng là chúng giữ nguyên thứ tự. Bạn biết một cách để giữ thuộc tính trường giống nhau đặt hàng?
wilbev 6/11/2016

Cảm ơn, đã sửa. Đối với thứ tự của các trường thuộc tính, chỉ cần thay đổi thứ tự của GeoPandas GeoDataFrame (= Pandas DataFrame)
gen

Cảm ơn Gene, nhưng tôi không chắc tôi hiểu nơi tôi sẽ thay đổi thứ tự đó trong mã ở đây. Tôi cũng đang gặp phải hai vấn đề khác với vấn đề này. Đầu tiên, tệp * .prj để trống trên tệp shp mới. Thứ hai, khi tôi cố mở tệp shp trong trình đọc shp, nó sẽ báo lỗi khi mở tệp như bị hỏng. Nó dường như hoạt động mà không bị hỏng nếu tệp shp chỉ có một tính năng duy nhất nhưng bội số là nơi nó gặp sự cố.
wilbev 7/11/2016

Xin lỗi, nhưng bạn cần biết Pandas về điều đó và tôi không có vấn đề gì với tập lệnh với dữ liệu của tôi (tôi sử dụng các phiên bản mới nhất của GeoPandas, Fiona và Numpy)
gen

Tôi có thể gửi cho bạn tệp shp để bạn có thể tự mình xem nhưng tệp shp này có hơn 250 cột dữ liệu mà tôi tưởng tượng đang tạo ra sự cố cho nó. Tôi đã thử điều này trên một tệp shp với ít thuộc tính hơn và dường như không có vấn đề gì.
wilbev

5

Khác, có lẽ nhiều hơn 'ở mức độ thấp, cách sẽ được sử dụng trực tiếp fionashapelycho I / O và xử lý hình học.

import fiona
from shapely.geometry import shape, mapping

with fiona.open('input_shapefile.shp') as src:
    meta = src.meta
    meta['schema']['geometry'] = 'Point'
    with fiona.open('output_shapefile.shp', 'w', **meta) as dst:
        for f in src:
            centroid = shape(f['geometry']).centroid
            f['geometry'] = mapping(centroid)
            dst.write(f)

Cảm ơn Loic. Điều đó chắc chắn khắc phục sự cố sắp xếp mà tôi gặp phải nhưng nó không khắc phục được sự cố với quá nhiều thuộc tính khiến tệp bị hỏng. Bạn có ý tưởng nào khác để khắc phục vấn đề đó không? Tôi đoán tôi có thể cần phải xóa các thuộc tính. Tôi có thể gửi cho bạn một tập tin ví dụ nếu nó sẽ giúp.
wilbev

@wilbev Gửi liên kết tải xuống dữ liệu của bạn nếu bạn có thể. Nếu không, tôi không thấy những gì có thể sai.
Loïc Dutrieux

Loic, tôi đã gửi email cho bạn một tập tin ví dụ. Hy vọng rằng điều đó mang lại cho bạn một ý tưởng tốt về vấn đề tôi đang gặp phải.
wilbev

@wilbev Ý của bạn là 'tập tin bị hỏng' là gì? Sử dụng tệp bạn đã gửi, tôi có thể tạo ra các centroid và mở shapefile đầu ra trong QGIS mà không gặp vấn đề gì. Bảng thuộc tính không thay đổi giữa cả hai tệp.
Loïc Dutrieux

Do hỏng, ý tôi là về cơ bản nó là một tệp dbf trống vì sau khi tôi chạy tập lệnh, nó tạo ra tệp dbf có kích thước 1 KB và khi bạn mở thì nó hoàn toàn trống. Nếu tôi chạy cùng một tập lệnh chính xác, tập lệnh bạn liệt kê ở trên, trên một tệp có ít thuộc tính hơn, nó sẽ hoạt động mà không gặp sự cố. Tôi thậm chí đã thử trên PC thứ hai và nhận được kết quả tương tự. Tôi không hiểu
wilbev

2

Tôi nghĩ cách dễ nhất là sử dụng gdal / ogr Virtual Format. ( http://www.gdal.org/drv_vrt.html ) và phương ngữ SQL / SQLITE ( http://www.gdal.org/ogr_sql.htmlhttps://www.gaia-gis.it/spatialite-3.0 .0-BETA / spatialite-sql-3.0.0.html )

Shapefile đa giác của tôi được đặt tên là poly.shp. Sau đó, tôi tạo tệp XML này giống như tệp có tên vrt.vrt. Bên trong tệp này (vrt.vrt), ở đây nội dung cần chuyển đổi thành điểm

<OGRVRTDataSource>
    <OGRVRTLayer name="poly">
        <SrcDataSource relativeToVRT="1">poly.shp</SrcDataSource>
        <SrcSQL dialect="sqlite">SELECT ST_PointOnSurface(geometry) as geom_point, poly.* from poly</SrcSQL>
        <GeometryType>wkbPoints</GeometryType> 
        <GeometryField name="geom_point" />
    </OGRVRTLayer>
</OGRVRTDataSource>

Tại thời điểm này, bạn có thể tích hợp tệp này vào Qgis để xác thực. Chắc chắn, kết xuất chậm hơn nguồn thô vì mọi tính năng được truyền dưới dạng điểm trên mỗi truy vấn kết xuất.

Sau đó, chuyển đổi tệp này (vrt.vrt) thành một thứ khác bằng cách sử dụng gdal / ogr utils từ shell / script python

os.system("ogr2ogr point_from_vrt.shp vrt.vrt poly")

Bạn nhận được một shapefile điểm có tên point_from_vrt.shp.


Tôi đã có thể làm cho nó hoạt động nhưng tôi muốn giữ tất cả những thứ này trong một tập lệnh python vì tôi cần phải chuyển đổi 100 tập tin với tất cả các tên tập tin khác nhau. Tôi muốn sử dụng giải pháp @Mike T nhưng tôi nhận được "Không có chức năng như vậy: ST_Centroid nếu tôi sử dụng giải pháp đó và tôi cũng đã thử ST_PointOnSurface, cũng nói rằng không có chức năng nào như vậy. ()?
wilbev

Tôi nhận được'wkbPoints' is not a valid value of the atomic type
Ben Sinclair
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.