Tạo số lượng lớn bản đồ bằng PyQGIS?


10

Tôi phải tạo ra một số lượng lớn (hàng trăm) bản đồ phân bố các loài. Tôi có một shapefile chứa các bản phân phối cho từng loài và đối với mỗi loài, tôi muốn lấy bản đồ dưới dạng hình ảnh (jpg, png hoặc cách khác) có chứa tên của loài đó, truyền thuyết (để phân biệt các khu vực phân phối hàng năm, chăn nuôi, không chăn nuôi, vv ...).

Tôi muốn sử dụng QGIS để làm điều này.


1
Bạn có thể chỉ định thêm một chút về các chi tiết cụ thể của bản đồ không? Ví dụ: bạn có muốn tất cả các bản đồ này hiển thị cùng một khu vực, như một lục địa hoặc quốc gia cụ thể hoặc bạn muốn phạm vi bản đồ thay đổi linh hoạt? Ngoài ra, bạn có muốn tất cả các kiểu con phạm vi trên một bản đồ hoặc chúng có trên nhiều bản đồ không? Tùy thuộc vào những câu trả lời này, vấn đề của bạn có thể khá đơn giản hoặc nó có thể đòi hỏi một chút cách tiếp cận tinh vi. Một nơi tốt để bắt đầu tìm kiếm là plugin Atlas cho GIS hoặc nếu bạn có sẵn ArcGIS 10 trở lên, các bản đồ của ESRI cũng sẽ giúp ích.
Jay Guarneri

1
Xin lỗi vì thiếu chi tiết. Có cho tất cả các bản đồ, nó sẽ là cùng một khu vực (Châu Âu). Tôi có một shapefile với tất cả các loài và, trong các thuộc tính, phân phối tương ứng. Shapefile này, tôi có thể dễ dàng chia nó thành các shapefile khác nhau (một cho mỗi loài). Cuối cùng, tôi muốn có cho mỗi loài một bức tranh, với mỗi lần, chính xác cùng một khu vực (Châu Âu), cùng màu (ví dụ: phân phối hàng năm trong màu xanh đậm, sinh sản trong màu xanh nhạt, không sinh sản trong màu xanh da trời, v.v ...), cùng một truyền thuyết và như tiêu đề tên của loài này.
Onesime

Tôi nghĩ rằng những gì bạn cần làm là lên kế hoạch cho từng bước bạn cần thực hiện để tạo từng bản đồ, sau đó mã hóa các lựa chọn và xuất bản đồ trong Python. Tôi biết điều này có thể được thực hiện dễ dàng trong ArcGIS Python, nhưng tôi không biết đủ về giao diện QGIS Python để đưa ra nhiều hướng dẫn. Tuy nhiên, tôi tự tin rằng bạn có thể thực hiện công việc này với một shapefile.
Jay Guarneri

Tôi đã làm một cái gì đó tương tự với QGIS bằng cách sử dụng plugin Python. Trong trường hợp của tôi, các lớp của tôi đã được lưu trữ trong PostGIS, nhưng tôi nghĩ bạn có thể làm điều gì đó tương tự bằng cách sử dụng một shapefile. Tôi rất vui được chia sẻ mã của tôi. Liên lạc tôi.
Brian Edmond

1
Bạn có thể tải lên một mẫu dữ liệu của bạn để chúng tôi chơi với.
Nathan W

Câu trả lời:


4

Tôi đã có một yêu cầu tương tự và kết hợp một plugin QGIS để tạo các bản đồ, dựa trên một shapefile với các địa phương điểm cho tất cả các loài (nó giả sử một tên đơn vị phân loại duy nhất trong bảng thuộc tính làm định danh chung). Yêu cầu của tôi không phức tạp - tôi không cần thông tin theo mùa, tiêu đề hoặc huyền thoại, nhưng nó có thể là điểm khởi đầu hữu ích cho bạn. Đối với các khía cạnh phức tạp hơn, bạn sẽ cần sử dụng trình soạn thảo bản đồ. Xem sách dạy nấu ăn PyQGIS để biết thêm về điều đó.

Cắm vào

Plugin tự động hóa việc tạo các bản đồ và cho phép bạn định cấu hình phạm vi, độ phân giải và các khía cạnh khác. Nó áp dụng cùng một kiểu cho đầu ra như lớp phủ lưới của bạn. Hiện tại, nó chỉ chạy trên phiên bản phát triển của QGIS (1.9 trở lên).

Kịch bản Sextante

Trước khi tôi tạo plugin, tôi đã xử lý logic bằng SEXTANTE. Tập lệnh người dùng này cũng sẽ hoạt động trong 1.8 (chưa được kiểm tra). Tệp kiểu phân phối (.qml) là kiểu của các bản phân phối đầu ra (nó bỏ qua kiểu của lớp phủ phân phối). Hiện tại, nó đặt các bản đồ đầu ra trong thư mục tạm thời dựa trên mặc định của hệ điều hành của bạn (/ tmp trong Linux và các vị trí khác nhau trong Windows - được xác định bởi biến môi trường TEMP). Bạn có thể dễ dàng xác định rằng trong mã. Bạn cũng sẽ cần chỉnh sửa phạm vi và độ phân giải đầu ra trong mã (và màu nền nếu bạn muốn một màu khác cho biển).

#Definition of inputs and outputs
#==================================
##[Scratch]=group
##all_localities=vector
##taxon_field=field all_localities
##africa_map=vector
##sa_map=vector
##grid_layer=vector
##distribution_style_file=file

#Algorithm body
#==================================
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
import tempfile
import os

def print_map(taxon,taxon_shp):
    #load taxon layer (necessary?)
    #QGisLayers.load(taxon_shp,name = "taxon",style = distribution_style_file)
    taxon_layer = QgsVectorLayer(taxon_shp,"taxon","ogr")
    QgsMapLayerRegistry.instance().addMapLayer(taxon_layer)
    taxon_layer.loadNamedStyle(distribution_style_file)

    # create image (dimensions 325x299)
    img = QImage(QSize(325,299), QImage.Format_ARGB32_Premultiplied)

    # set image's background color
    color = QColor(192,192,255)   # blue sea
    img.fill(color.rgb())

    # create painter
    p = QPainter()
    p.begin(img)
    p.setRenderHint(QPainter.Antialiasing)

    render = QgsMapRenderer()

    # create layer set
    africa_layer = QGisLayers.getObjectFromUri(africa_map)
    sa_layer = QGisLayers.getObjectFromUri(sa_map)
    #taxon_layer = QGisLayers.getObjectFromUri(taxon_shp)

    lst = []
    lst.append(taxon_layer.id())    
    lst.append(sa_layer.id())
    lst.append(africa_layer.id())

    render.setLayerSet(lst)

    # set extent (xmin,ymin,xmax,ymax)
    rect = QgsRectangle(14.75,-36.00,34.00,-21.00)
    render.setExtent(rect)

    # set output size
    render.setOutputSize(img.size(), img.logicalDpiX())

    # do the rendering
    render.render(p)
    p.end()

    # save image
    #outdir = os.path.dirname(os.path.abspath(output))
    tempdir = tempfile.gettempdir()
    img.save(os.path.join(tempdir,taxon+".png"),"png")

    # remove taxon layer from project
    QgsMapLayerRegistry.instance().removeMapLayers([taxon_layer.id()])

tempdir = tempfile.gettempdir()   
taxa = sextante.runalg('qgis:listuniquevalues', all_localities, taxon_field, None)['UNIQUE_VALUES'].split(";")
for taxon in taxa:
    sextante.runalg('qgis:selectbyattribute', all_localities, taxon_field, 0, taxon)
    sextante.runalg('qgis:selectbylocation', grid_layer, all_localities, 0)
    filename = os.path.join(tempdir,"taxon.shp")    #memory file better?
    sextante.runalg('qgis:saveselectedfeatures', grid_layer, filename)
    print_map(taxon,filename)

Hi tất cả, Cảm ơn tất cả các câu trả lời của bạn. Để cung cấp cho bạn thêm một số yếu tố, đó là dữ liệu đến từ BirdLife (một ví dụ cho specie: birdlife.org/datazone/speciesfactsheet.php?id=2794 ). Tóm lại, có một shapefile với tất cả các đa giác cho tất cả các loài (vì vậy, đối với một số trong số chúng, nhiều dòng cho một loài), và có một thuộc tính tương ứng với phân phối theo mùa (với các giá trị từ 1 đến 5 tương ứng với các cách sử dụng khác nhau ), một cái khác cho nguồn gốc, vv .. Truyền thuyết và tiêu đề không thể thiếu.
Onesime

- Tôi sử dụng một lớp quốc gia trong nền, chỉ cho một vị trí dễ dàng. - Đối với màu khác nhau cho giá trị khác với thuộc tính "theo mùa", tôi nghĩ rằng, sử dụng tệp .qml là phù hợp. - Tùy chọn, đối với tiêu đề và chú giải, tôi nghĩ rằng tôi phải sử dụng một tệp từ nhà soạn nhạc, nếu quá khó, tôi có thể thêm nó bằng một phần mềm khác. - Thao tác phải được lặp lại cho tất cả các loài, vì vậy, điều này tương ứng với lựa chọn theo thuộc tính, sẽ được sử dụng để đưa ra tên của hình ảnh cuối cùng.
Onesime

Tôi đã thử plugin "Atlas", nhưng nó có vẻ phù hợp hơn cho các địa điểm khác nhau, trong trường hợp của tôi, đó là tất cả thời gian cho cùng một khu vực: Châu Âu. Tôi đã thử plugin "Trình quản lý bản đồ phân phối" có vẻ tương ứng ở điểm này vì có thể sửa vùng phủ sóng, nhưng tôi không cần quá trình giao điểm với lớp lưới vì tôi đã có lớp đa giác. Tôi đã thử trong ArcGis, nhưng nó khá giống với plugin QGis Atlas, giải pháp có vẻ là viết một kịch bản python ...
Onesime 13/03/13

Vì vậy, tôi nghĩ rằng tôi sẽ sử dụng Sextante, dựa trên kịch bản "rudivonstaden" (cảm ơn bạn vì điều đó!) Và để điều chỉnh nó phù hợp với trường hợp của tôi. Cuối cùng, Xin lỗi vì những bình luận khác nhau này, nhưng có giới hạn số lượng ký tự ...
Onesime 13/03/13

@Onesime, ngoại trừ tiêu đề và truyền thuyết, tôi nghĩ bạn sẽ có thể điều chỉnh kịch bản sextante ở trên để làm những gì bạn cần. Bạn sẽ cần phải có thể loại bỏ các selectbylocationbước, và bổ sung thêm một selectbyattributesaveselectedfeaturesbước cho mỗi mùa (thay đổi grid_layerđể all_localities). Sau đó tải thêm các tệp .qml và thêm vào các shapefiles theo mùa của bạn (lớp trên cùng được nối trước). Nếu bạn không chắc chắn làm thế nào, có lẽ tôi có thể thử chỉnh sửa tập lệnh ở trên để hoạt động nhiều hơn hoặc ít hơn.
rudivonstaden

2

Tôi đã dành ít thời gian để làm việc này ngày hôm nay. Vì vậy, tôi đã thực hiện một số thay đổi cho kịch bản của bạn. Tôi không cần phải thêm một bước chọn lọc bổ sung và lưu các tính năng được chọn khi tôi sử dụng tệp .qml và trường theo Mùa nằm trong cùng một shapefile. Dưới đây, bạn có thể thấy những gì tôi đã làm:

#Definition of inputs and outputs
#==================================
##[Scratch]=group
##all_localities=vector
##taxon_field=field all_localities
##seasonal_field=field all_localities
##countries_map=vector
##distribution_style_file=file
##output_folder=folder

#Algorithm body
#==================================
from qgis.core import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.core.QGisLayers import QGisLayers
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
import tempfile
import os

def print_map(taxon,taxon_shp):
#load taxon layer (necessary?)
#QGisLayers.load(taxon_shp,name = "taxon",style = distribution_style_file)
taxon_layer = QgsVectorLayer(taxon_shp,"taxon","ogr")
QgsMapLayerRegistry.instance().addMapLayer(taxon_layer)
taxon_layer.loadNamedStyle(distribution_style_file)

# create image (dimensions 325x299)
img = QImage(QSize(325,299), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(221,249,254)   # blue sea
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# create layer set
countries_layer = QGisLayers.getObjectFromUri(countries_map)
taxon_layer = QGisLayers.getObjectFromUri(taxon_shp)

lst = []
lst.append(taxon_layer.id())    
lst.append(countries_layer.id())
render.setLayerSet(lst)

# set extent (xmin,ymin,xmax,ymax)
rect = QgsRectangle(-11,32,39,71)
render.setExtent(rect)
# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)
p.end()

#save image
#outdir = os.path.dirname(os.path.abspath(output))
tempdir = output_folder
img.save(os.path.join(tempdir,taxon+".png"),"png")

# remove taxon layer from project
QgsMapLayerRegistry.instance().removeMapLayers([taxon_layer.id()])

tempdir = tempfile.gettempdir()  

taxa = sextante.runalg('qgis:listuniquevalues', all_localities, taxon_field, None)        ['UNIQUE_VALUES'].split(";")

for taxon in taxa:
sextante.runalg('qgis:selectbyattribute', all_localities, taxon_field, 0, taxon)
filename = os.path.join(tempdir,"taxon.shp")    #memory file better?
sextante.runalg('qgis:saveselectedfeatures', all_localities, filename)
print_map(taxon,filename)

Nếu bạn có bất kỳ nhận xét hoặc lời khuyên để cải thiện nó, đừng ngần ngại.

Để cải thiện nó, tốt nhất là khi chúng ta chọn phạm vi (đối với Châu Âu mẫu mực), nó sử dụng phạm vi này để chỉ chọn các loài được bao gồm trong phạm vi này. Điều này, bởi vì tôi có được bản đồ cho tất cả các loài, ngay cả những loài ở ngoài châu Âu chẳng hạn (vì vậy tôi có nhiều bản đồ trống). Bạn có nghĩ rằng điều đó là có thể?

Chúc mừng

Thời gian

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.