กำลังสร้างแผนที่จำนวนมากโดยใช้ PyQGIS ใช่ไหม


10

ฉันต้องทำแผนที่สายพันธุ์กระจายจำนวนมาก (ร้อย) ฉันมีไฟล์รูปร่างที่มีการแจกแจงสำหรับสปีชีส์แต่ละชนิดและสำหรับแต่ละสปีชีส์ฉันต้องการแผนที่เป็นรูปภาพ (jpg, png หรืออื่น ๆ ) ซึ่งมีชื่อสปีชีส์ที่เกี่ยวข้องตำนาน (เพื่อแยกแยะพื้นที่ของ การแจกแจงรายปีการผสมพันธุ์การผสมพันธุ์และอื่น ๆ

ฉันต้องการใช้ QGIS เพื่อทำสิ่งนี้


1
คุณช่วยระบุเพิ่มเติมเล็กน้อยเกี่ยวกับแผนที่เฉพาะได้หรือไม่? ตัวอย่างเช่นคุณต้องการให้แผนที่ทั้งหมดเหล่านี้แสดงพื้นที่เดียวกันเช่นทวีปหรือประเทศที่เฉพาะเจาะจงหรือคุณต้องการให้ขอบเขตแผนที่เปลี่ยนแบบไดนามิกหรือไม่ นอกจากนี้คุณต้องการให้ทุกประเภทย่อยของช่วงบนแผนที่เดียวหรืออยู่ในหลายแผนที่หรือไม่? ปัญหาของคุณอาจค่อนข้างง่ายหรืออาจต้องใช้วิธีการที่ซับซ้อนมากขึ้นอยู่กับคำตอบเหล่านี้ จุดเริ่มต้นที่ดีในการมองหาคือปลั๊กอินของ Atlas สำหรับ GIS หรือถ้าคุณมี ArcGIS 10 ขึ้นไปที่มีอยู่ mapbooks ของ ESRI ก็จะช่วยได้เช่นกัน
Jay Guarneri

1
ขออภัยที่ไม่มีรายละเอียด ใช่สำหรับแผนที่ทั้งหมดมันจะเป็นพื้นที่เดียวกัน (ยุโรป) ฉันมีหนึ่ง shapefile กับสปีชีส์ทั้งหมดและในการกระจายแอตทริบิวต์ที่สอดคล้องกัน ไฟล์รูปร่างนี้ฉันสามารถแยกมันได้อย่างง่ายดายในรูปร่างที่แตกต่างกัน (หนึ่งไฟล์สำหรับแต่ละสปีชีส์) ในตอนท้ายฉันต้องการให้แต่ละสปีชีส์หนึ่งภาพโดยในแต่ละครั้งพื้นที่เดียวกัน (ยุโรป) มีสีเดียวกัน (ตัวอย่างเช่นการกระจายประจำปีในสีเขียวเข้ม, การผสมพันธุ์ในสีเขียวอ่อน, ไม่ใช่การผสมพันธุ์ใน สีฟ้า ฯลฯ .. ) ตำนานเดียวกันและเป็นชื่อของสายพันธุ์
Onesime

ฉันคิดว่าสิ่งที่คุณต้องทำคือการวางแผนในแต่ละขั้นตอนที่คุณต้องทำเพื่อทำแผนที่แต่ละขั้นจากนั้นให้เขียนรหัสการเลือกและการส่งออกแผนที่ใน Python ฉันรู้ว่าสิ่งนี้สามารถทำได้อย่างง่ายดายใน ArcGIS Python แต่ฉันไม่รู้เกี่ยวกับอินเตอร์เฟส QGIS Python มากพอที่จะให้คำแนะนำได้ อย่างไรก็ตามฉันมั่นใจว่าคุณสามารถใช้งานได้กับหนึ่งไฟล์รูปร่าง
Jay Guarneri

ฉันทำสิ่งที่คล้ายกับ QGIS โดยใช้ปลั๊กอิน Python ในกรณีของฉันเลเยอร์ของฉันถูกเก็บไว้ใน PostGIS แต่ฉันคิดว่าคุณสามารถทำสิ่งที่คล้ายกันโดยใช้ shapefile ฉันยินดีที่จะแบ่งปันรหัสของฉัน PM ฉัน
Brian Edmond

1
คุณสามารถอัปโหลดตัวอย่างข้อมูลของคุณเพื่อให้เราเล่นด้วยได้หรือไม่
นาธาน W

คำตอบ:


4

ฉันมีความต้องการที่คล้ายกันและรวบรวมปลั๊กอิน QGIS เพื่อสร้างแผนที่โดยอิงจากไฟล์รูปร่างที่มีจุดท้องถิ่นสำหรับสปีชีส์ทั้งหมด (จะถือว่าชื่อแท็กซอนที่ไม่ซ้ำกันในตารางแอตทริบิวต์เป็นตัวระบุทั่วไป) ความต้องการของฉันไม่ซับซ้อน - ฉันไม่ต้องการข้อมูลตามฤดูกาลชื่อเรื่องหรือคำอธิบายภาพ แต่มันอาจเป็นจุดเริ่มต้นที่มีประโยชน์สำหรับคุณ สำหรับแง่มุมที่ซับซ้อนยิ่งขึ้นคุณจะต้องใช้ผู้แต่งแผนที่ ดูตำรา PyQGISสำหรับข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนั้น

เสียบเข้าไป

ปลั๊กอินทำการสร้างแผนที่โดยอัตโนมัติและช่วยให้คุณกำหนดค่าขอบเขตความละเอียดและด้านอื่น ๆ มันใช้รูปแบบเดียวกันกับการส่งออกเป็นตารางซ้อนทับของคุณ ขณะนี้มันทำงานเฉพาะกับรุ่นพัฒนาของ QGIS (1.9 หรือใหม่กว่า)

สคริปต์ Sextante

ก่อนที่ฉันจะสร้างปลั๊กอินฉันใช้ตรรกะโดยใช้ SEXTANTE สคริปต์ผู้ใช้นี้ควรใช้งานได้ใน 1.8 (ยังไม่ได้ทดสอบ) ไฟล์ลักษณะการแจกจ่าย (.qml) เป็นรูปแบบของการแจกแจงเอาต์พุต (จะละเว้นสไตล์ของการซ้อนทับการกระจาย) ขณะนี้วางแผนที่แสดงผลในไดเรกทอรีชั่วคราวตามค่าเริ่มต้นของระบบปฏิบัติการ (/ tmp ใน Linux และสถานที่ต่าง ๆ ใน Windows - กำหนดโดยตัวแปรสภาพแวดล้อม TEMP) คุณสามารถกำหนดได้ด้วยตัวเองในรหัส คุณจะต้องแก้ไขขอบเขตและความละเอียดผลงานในรหัส (และสีพื้นหลังหากคุณต้องการสีที่แตกต่างกันสำหรับทะเล)

#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)

สวัสดีทุกคนขอบคุณสำหรับคำตอบของคุณ เพื่อให้องค์ประกอบเพิ่มเติมแก่คุณมันเป็นข้อมูลที่มาจาก BirdLife (ตัวอย่างสำหรับ specie: birdlife.org/datazone/speciesfactsheet.php?id=2794 ) สั้น ๆ มีรูปร่างหนึ่งไฟล์ที่มีรูปหลายเหลี่ยมทั้งหมดสำหรับทุกสปีชีส์ (ดังนั้นสำหรับบางสปีชีส์หลายบรรทัดสำหรับสปีชีส์เดี่ยว) และมีแอตทริบิวต์ที่สอดคล้องกับการแจกแจงตามฤดูกาล ) อีกรายการหนึ่งสำหรับจุดเริ่มต้นเป็นต้นตำนานและชื่อเรื่องที่ขาดไม่ได้
Onesime

- ฉันใช้เลเยอร์ประเทศเป็นพื้นหลังเพื่อให้ได้ตำแหน่งที่ง่าย - สำหรับสีที่ต่างกันสำหรับค่าที่แตกต่างจากแอตทริบิวต์ "ฤดูกาล" ฉันคิดว่าไฟล์. qml เหมาะสม - อีกทางเลือกหนึ่งสำหรับชื่อและคำอธิบายฉันคิดว่าฉันต้องใช้ไฟล์จากผู้แต่งถ้ามันยากเกินไปฉันสามารถเพิ่มมันด้วยซอฟต์แวร์อื่น - การดำเนินการจะต้องมีการทำซ้ำสำหรับทุกสายพันธุ์ดังนั้นสิ่งนี้สอดคล้องกับการเลือกโดยแอตทริบิวต์ซึ่งจะถูกใช้เพื่อให้ชื่อของภาพสุดท้าย
Onesime

ฉันลองใช้ปลั๊กอิน "Atlas" แต่ดูเหมือนว่าจะเหมาะสมกว่าสำหรับสถานที่ต่าง ๆ ในกรณีของฉันมันตลอดเวลาสำหรับพื้นที่เดียวกัน: ยุโรป ฉันลองใช้ปลั๊กอิน "ตัวจัดการแผนที่การกระจาย" ซึ่งดูเหมือนจะสอดคล้องกันในจุดนี้เพราะมันเป็นไปได้ที่จะแก้ไขพื้นที่ครอบคลุม แต่ฉันไม่ต้องการกระบวนการที่ตัดจุดที่มีเลเยอร์กริดเนื่องจากฉันมีเลเยอร์หลายเหลี่ยมอยู่แล้ว ฉันพยายามใน ArcGis แต่มันค่อนข้างเหมือนกันกับปลั๊กอิน QGis Atlas ดูเหมือนว่าโซลูชันจะเขียนสคริปต์ python ...
Onesime

ดังนั้นฉันคิดว่าฉันจะใช้ Sextante ตามสคริปต์ "rudivonstaden" (ขอบคุณสำหรับมัน!) และปรับให้เข้ากับกรณีของฉัน ในที่สุดขออภัยสำหรับความคิดเห็นที่แตกต่างกันเหล่านี้ แต่มีการ จำกัด จำนวนอักขระ ...
Onesime

@Oimeime ยกเว้นชื่อและตำนานฉันคิดว่าคุณจะสามารถปรับสคริปต์ sextante ด้านบนเพื่อทำสิ่งที่คุณต้องการ คุณจะต้องอาจจะเอาselectbylocationขั้นตอนและเพิ่มอีกselectbyattributeและsaveselectedfeaturesขั้นตอนในแต่ละฤดูกาล (เปลี่ยนgrid_layerไปall_localities) จากนั้นโหลดไฟล์. qml เพิ่มเติมและเพิ่มผนวกไฟล์รูปร่างตามฤดูกาลของคุณ (ชั้นบนสุดผนวกก่อน) หากคุณไม่แน่ใจฉันอาจลองแก้ไขสคริปต์ด้านบนเพื่อทำงานที่มากหรือน้อย
rudivonstaden

2

วันนี้ฉันใช้เวลาไม่กี่นาที ดังนั้นฉันจึงเปลี่ยนแปลงสคริปต์ของคุณ ฉันไม่จำเป็นต้องเพิ่มขั้นตอนการเลือกตัวเลือกเพิ่มเติมและคุณสมบัติตัวเลือกคัดสรรขณะที่ฉันใช้ไฟล์. qml และฟิลด์ฤดูกาลอยู่ในรูปแบบไฟล์เดียวกัน ด้านล่างคุณสามารถเห็นสิ่งที่ฉันทำ:

#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)

หากคุณมีข้อสังเกตหรือคำแนะนำในการปรับปรุงอย่าลังเล

ในการปรับปรุงมันสิ่งที่ดีที่สุดคือเมื่อเราเลือกขอบเขต (สำหรับตัวอย่างของยุโรป) เราใช้ขอบเขตนี้เพื่อเลือกเฉพาะสายพันธุ์ที่รวมอยู่ในขอบเขตนี้ นี่เพราะฉันได้รับแผนที่สำหรับสัตว์ทุกชนิดแม้แต่พวกที่อยู่นอกยุโรปเช่นกัน (ดังนั้นฉันจึงมีแผนที่ที่ว่างเปล่ามากมาย) คุณคิดว่าเป็นไปได้หรือไม่

ไชโย

Onesime

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.