চিত্র সংরক্ষণের আগে ক্যানভাস রেন্ডারিং শেষ করার জন্য অপেক্ষা করুন


11

আমি এমন একটি স্ক্রিপ্ট লেখার চেষ্টা করছি যা মানচিত্রের রচয়িতা ব্যবহার করে কয়েকটি স্তরকে রেন্ডারিং সাশ্রয় করবে। আমি যে সমস্যার মুখোমুখি হচ্ছি তা হ'ল Qgis সমস্ত স্তরকে রেন্ডারিং শেষ করার আগে স্ক্রিপ্টটি সংরক্ষণ করে।

অন্যান্য বেশ কয়েকটি উত্তরের উপর ভিত্তি করে ( 1 , 2 , 3 ), আমি iface.mapCanvas.mapCanvasRefreshed.connect()কোনও ফাংশনের অভ্যন্তরে চিত্রটি সংরক্ষণ করার চেষ্টা করেছি এবং এখনও আমি একই সমস্যাটির মুখোমুখি হয়েছি - চিত্রগুলিতে সমস্ত স্তর অন্তর্ভুক্ত নয়।

আমি যে কোডটি ব্যবহার করছি সেগুলি পাশাপাশি মূল উইন্ডো এবং রেন্ডারিংগুলি দেখতে কেমন তার চিত্রগুলি নীচে তালিকাভুক্ত করা হয়েছে।

আমি লক্ষ করেছি যে আমার কাছে যদি কনসোল উইন্ডোটি খোলা থাকে এবং তিনটি print layerListলাইনকে সংস্থাপিত করা হয় , তবে প্রোগ্রামটি চিত্রগুলি সংরক্ষণের আগে শেষ হওয়ার জন্য অপেক্ষা করবে। প্রসেসিংয়ের বর্ধিত সময়ের কারণে এটি হয়েছে কিনা বা প্রোগ্রামটি কীভাবে কার্যকর করে তা যদি এটি পরিবর্তন করে থাকে তবে আমি নিশ্চিত নই।

আমি কীভাবে এটি সঠিকভাবে বাস্তবায়ন করব যাতে সমস্ত স্তরটি চিত্রটিতে অন্তর্ভুক্ত থাকে?

from qgis.core import *
from qgis.utils import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import os.path

##StackExchange Version=name
##Map_Save_Folder=folder
##Map_Save_Name=string roadmap

# Create save file location
mapName = "%s.png" %Map_Save_Name
outfile = os.path.join(Map_Save_Folder,mapName)
pdfName = "%s.pdf" %Map_Save_Name
outPDF = os.path.join(Map_Save_Folder,pdfName)

# Create point and line layers for later
URIstrP = "Point?crs=EPSG:3035"
layerP = QgsVectorLayer(URIstrP,"pointsPath","memory")
provP = layerP.dataProvider()
URIstrL = "LineString?crs=EPSG:3035"
layerL = QgsVectorLayer(URIstrL,"linePath","memory")
provL = layerL.dataProvider()

# Add points to point layer
feat1 = QgsFeature()
feat2 = QgsFeature()
feat3 = QgsFeature()
feat1.setGeometry(QgsGeometry.fromPoint(QgsPoint(5200000,2600000)))
feat2.setGeometry(QgsGeometry.fromPoint(QgsPoint(5300000,2800000)))
provP.addFeatures([feat1, feat2])

# Add line to line layer
feat3.setGeometry(QgsGeometry.fromPolyline([feat1.geometry().asPoint(),feat2.geometry().asPoint()]))
provL.addFeatures([feat3])

# Set symbology for line layer
symReg = QgsSymbolLayerV2Registry.instance()
metaRegL = symReg.symbolLayerMetadata("SimpleLine")
symLayL = QgsSymbolV2.defaultSymbol(layerL.geometryType())
metaL = metaRegL.createSymbolLayer({'width':'1','color':'0,0,0'})
symLayL.deleteSymbolLayer(0)
symLayL.appendSymbolLayer(metaL)
symRendL = QgsSingleSymbolRendererV2(symLayL)
layerL.setRendererV2(symRendL)

# Set symbology for point layer
metaRegP = symReg.symbolLayerMetadata("SimpleMarker")
symLayP = QgsSymbolV2.defaultSymbol(layerP.geometryType())
metaP = metaRegP.createSymbolLayer({'size':'3','color':'0,0,0'})
symLayP.deleteSymbolLayer(0)
symLayP.appendSymbolLayer(metaP)
symRendP = QgsSingleSymbolRendererV2(symLayP)
layerP.setRendererV2(symRendP)

# Load the layers
QgsMapLayerRegistry.instance().addMapLayer(layerP)
QgsMapLayerRegistry.instance().addMapLayer(layerL)
iface.mapCanvas().refresh()


# --------------------- Using Map Composer -----------------
def custFunc():
    mapComp.exportAsPDF(outPDF)
    mapImage.save(outfile,"png")
    mapCanv.mapCanvasRefreshed.disconnect(custFunc)
    return

layerList = []
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
    layerList.append(layer.id())
#print layerList
#print layerList
#print layerList

mapCanv = iface.mapCanvas()
bound = layerP.extent()
bound.scale(1.25)
mapCanv.setExtent(bound)

mapRend = mapCanv.mapRenderer()
mapComp = QgsComposition(mapRend)
mapComp.setPaperSize(250,250)
mapComp.setPlotStyle(QgsComposition.Print)

x, y = 0, 0
w, h = mapComp.paperWidth(), mapComp.paperHeight()

composerMap = QgsComposerMap(mapComp, x, y, w, h)
composerMap.zoomToExtent(bound)
mapComp.addItem(composerMap)
#mapComp.exportAsPDF(outPDF)

mapRend.setLayerSet(layerList)
mapRend.setExtent(bound)

dpmm = dpmm = mapComp.printResolution() / 25.4
mapImage = QImage(QSize(int(dpmm*w),int(dpmm*h)), QImage.Format_ARGB32)
mapImage.setDotsPerMeterX(dpmm * 1000)
mapImage.setDotsPerMeterY(dpmm * 1000)

mapPaint = QPainter()
mapPaint.begin(mapImage)

mapRend.render(mapPaint)

mapComp.renderPage(mapPaint,0)
mapPaint.end()
mapCanv.mapCanvasRefreshed.connect(custFunc)
#mapImage.save(outfile,"png")

কিউজিআইএস মূল উইন্ডোতে এটি দেখতে কেমন দেখাচ্ছে (এটিতে প্রদর্শিত হচ্ছে একটি এলোমেলো রাস্টার মানচিত্র): এখানে চিত্র বর্ণনা লিখুন

কি সংরক্ষিত হয়: এখানে চিত্র বর্ণনা লিখুন

আরও তথ্য হিসাবে, আমি উইন্ডোজ 7 এ কিউজিআইএস 2.18.7 ব্যবহার করছি .7


আমি বেশ কয়েকটি ওয়েব পৃষ্ঠাগুলি উল্লেখ করেছি, 1 এবং 2 । আমি এগুলিকে পোস্ট হওয়ার জন্য যুক্ত করার চেষ্টা করেছি, তবে আমার প্রতিবেদনটি যথেষ্ট বেশি নয়
ইস্ট ওয়েস্ট

আপনার দ্বিতীয় শেষ লাইনে, এর mapCanv.mapCanvasRefreshed.connect(custFunc)সাথে প্রতিস্থাপনের চেষ্টা করবেন mapCanv.renderComplete.connect(custFunc)?
জোসেফ

@ জোসেফ দুর্ভাগ্যক্রমে, এটি কোনও পার্থক্য বলে মনে হচ্ছে না। আমি এখনও উপরের মতো একই ফলাফলটি পেয়েছি
ইস্টওয়েস্ট

সম্ভবত আপনি স্তরটিতে যুক্ত হওয়া বৈশিষ্ট্যগুলি ঘটাতে চেষ্টা করবেন? (অর্থাত্ layerP .commitChanges()) যদিও আমি দেখতে পাচ্ছি না কেন এটি কেন সাহায্য করবে কারণ আপনি কেবল চিত্রটি সংরক্ষণ করছেন তবে আমার অনুধাবনের চেষ্টা worth অন্যথায় আশা করি অন্যরা পরামর্শ দিতে পারেন :)
জোসেফ

দুর্ভাগ্যক্রমে, আমি জোসেফ চেষ্টা করেছি commitChanges(), কিন্তু ভাগ্য নেই। পরামর্শের জন্য ধন্যবাদ.
পূর্ব

উত্তর:


5

এখানে surfacing বিভিন্ন সমস্যা আছে

স্ক্রিনে রেন্ডারিং বনাম কোনও চিত্রের রেন্ডারিং

mapCanvasRefreshedক্যানভাসটি স্ক্রিনে রেন্ডার হওয়ার সময় সংকেতটি বারবার নির্গত হয়। অন-স্ক্রিন-ডিসপ্লেতে এটি একটি দ্রুত প্রতিক্রিয়া দেয় যা ব্যবহারকারীর পক্ষে কিছু চলছে বা নেভিগেশনে সহায়তা করা ভাল be

কোনও স্কুলে রেকর্ডিংয়ের মতো কোনও ফাইল সাশ্রয়ের জন্য এটি নির্ভরযোগ্য নয় (কারণ কেবলমাত্র রেন্ডারিং যথেষ্ট দ্রুত হলে আপনার একটি সম্পূর্ণ চিত্র থাকবে)।

কী করা যায়: আপনার চিত্রটি রেন্ডার করতে আমাদের মানচিত্রের ক্যানভাসের দরকার নেই। আমরা কেবল QgsMapSettingsমানচিত্রের ক্যানভাস থেকে অনুলিপি করতে পারি । এই সেটিংস হ'ল প্যারামিটারগুলি যা রেন্ডারকে প্রেরণ করা হয় এবং নির্ধারণ করে যে কী এবং ঠিক কীভাবে সমস্ত ডেটা সরবরাহকারীদের থেকে কোনও রেস্টার ইমেজে রূপান্তর করা উচিত।

স্তর রেজিস্ট্রি বনাম মানচিত্রের ক্যানভাস

রেজিস্ট্রিতে যুক্ত স্তরগুলি ক্যানভাসে অবিলম্বে শেষ হয় না তবে কেবল ইভেন্ট লুপের পরবর্তী রানে। অতএব আপনি নিম্নলিখিত দুটি কাজের একটি করা থেকে ভাল

  • একটি টাইমার মধ্যে চিত্র উপস্থাপনা শুরু করুন। QTimer.singleShot(10, render_image)

  • QApplication.processEvents()স্তর যোগ করার পরে চালান । এটি কাজ করে তবে এটি ব্যবহারের জন্য একটি বিপজ্জনক কল (কখনও কখনও অদ্ভুত ক্র্যাশ হয়) এবং তাই এড়ানো উচিত।

আমাকে কোডটি দেখান

নিম্নলিখিত কোডটি এটি করে ( কিউফিল্ডসিঙ্ক থেকে কিছুটা সামঞ্জস্য হয়েছে , আপনি যদি আরও কাস্টমাইজেশনে আগ্রহী হন তবে সেখানে একবার দেখুন)

from PyQt4.QtGui import QImage, QPainter

def render_image():
    size = iface.mapCanvas().size()
    image = QImage(size, QImage.Format_RGB32)

    painter = QPainter(image)
    settings = iface.mapCanvas().mapSettings()

    # You can fine tune the settings here for different
    # dpi, extent, antialiasing...
    # Just make sure the size of the target image matches

    # You can also add additional layers. In the case here,
    # this helps to add layers that haven't been added to the
    # canvas yet
    layers = settings.layers()
    settings.setLayers([layerP.id(), layerL.id()] + layers)

    job = QgsMapRendererCustomPainterJob(settings, painter)
    job.renderSynchronously()
    painter.end()
    image.save('/tmp/image.png')

# If you don't want to add additional layers manually to the
# mapSettings() you can also do this:
# Give QGIS give a tiny bit of time to bring the layers from 
# the registry to the canvas (the 10 ms do not matter, the important
# part is that it's posted to the event loop)

# QTimer.singleShot(10, render_image)

1
renderCompleteসিগন্যাল সম্পর্কে কোন ধারণা কাজ করছে না?
জোসেফ

সকল তথ্যের জন্য ধন্যবাদ! দুর্ভাগ্যক্রমে, আমি আমার স্ক্রিপ্টে প্রস্তাবিত কোডটি triedোকানোর চেষ্টা করেছি, মানচিত্রের সুরকার বিভাগটি পুরোপুরি প্রতিস্থাপন করে এবং এখনও একই সমস্যাটির মুখোমুখি হয়েছি। সংরক্ষিত চিত্রটিতে লাইন বা পয়েন্ট স্তরগুলি অন্তর্ভুক্ত নেই, কেবল প্রাক লোড রাস্টার।
ইস্টওয়েস্ট

আমি মনে করি কাজের মধ্যে সিগন্যাল নির্গত হয় এবং চিত্রটি পর্দায় টানা হয়। painterএটির সাথে একটি প্যারামিটার নির্গত হয় যার উপর আপনি চূড়ান্ত চিত্রটিতে শেষ হওয়া অতিরিক্ত জিনিসগুলি আঁকতে পারেন (এবং যা থেকে আপনি সম্ভবত এই পদ্ধতির কাজ করতে চূড়ান্ত চিত্রও নিতে পারেন)।
ম্যাথিয়াস কুহন

1
এটি সমাধানের মতো দেখাচ্ছে। সব আপনার সাহায্যের জন্য ধন্যবাদ। একটি দ্রুত নোট অন্য কেউ যদি এটি সন্ধান করে শেষ করে - কিউটাইমারকে সঠিকভাবে কাজ করতে পেতে, রেন্ডার_আইমেজের পরে প্রথম বন্ধনী ছেড়ে দিন, বা অন্যথায় পাইথন একটি সতর্কতা নিক্ষেপ করে। পড়া উচিতQTimer.singleShot(10, render_image)
ইস্টওয়েস্ট

উফ, অবশ্যই। উপরের
ম্যাথিয়াস কুহান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.