def setUnitParameterValue(self, value): units = QgsUnitTypes.DistanceUnknownUnit layer = self.getLayerFromValue(value) if isinstance(layer, QgsMapLayer): units = layer.crs().mapUnits() elif isinstance(value, QgsCoordinateReferenceSystem): units = value.mapUnits() elif isinstance(value, str): crs = QgsCoordinateReferenceSystem(value) if crs.isValid(): units = crs.mapUnits() self.setUnits(units)
def printToPdf(self, params): self.check_required_params(params) with change_directory(self.project_root): crs = QgsCoordinateReferenceSystem() crs.createFromSrid(params.get('srs')) mapRenderer = QgsMapRenderer() mapUnits = crs.mapUnits() mapRenderer.setMapUnits(mapUnits) mapExtent = QgsRectangle(*params.get('bbox')) mapRenderer.setExtent(mapExtent) le = QgsPalLabeling() mapRenderer.setLabelingEngine(le) layers = params.get('layers') self.setTransparencies(layers, params.get('transparencies')) mapRenderer.setLayerSet(layers) composer = ( self.getLayoutbyName(params['layout']) .firstChildElement('Composition') ) comp = QgsComposition(mapRenderer) comp.setPlotStyle(QgsComposition.Print) comp.readXML(composer, self.doc) # read composition elements comp.addItemsFromXML(composer, self.doc) comp.setPrintResolution(90) # set bbox for the first Map in the layout comp_map = comp.getComposerMapById(0) comp_map.setNewExtent(QgsRectangle(*params.get('bbox'))) # comp_map.setNewScale(10000) # comp_map.setLayerSet(layers) # comp_map.setKeepLayerSet(True) # save the file comp.exportAsPDF(params['tmpFile'] + '.pdf')
def getBaseMapSettings(cls): """ :rtype: QgsMapSettings """ ms = QgsMapSettings() crs = QgsCoordinateReferenceSystem() """:type: QgsCoordinateReferenceSystem""" # default for labeling test data: WGS 84 / UTM zone 13N crs.createFromSrid(32613) ms.setBackgroundColor(QColor(152, 219, 249)) ms.setOutputSize(QSize(420, 280)) ms.setOutputDpi(72) ms.setFlag(QgsMapSettings.Antialiasing) ms.setDestinationCrs(crs) ms.setCrsTransformEnabled(False) ms.setMapUnits(crs.mapUnits()) # meters ms.setExtent(cls.aoiExtent()) return ms
if __name__ == '__console__': print("-----------------------------------------------\n\n") # PostGIS SRID 4326 is allocated for WGS84 # If not specified otherwise in second parameter, PostGIS SRID is used by default. crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId) print("Valid: ", crs.isValid()) print("QGIS CRS ID:", crs.srsid()) print("EPSG ID:", crs.authid()) print("Description:", crs.description()) print("Projection Acronym:", crs.projectionAcronym()) print("Ellipsoid Acronym:", crs.ellipsoidAcronym()) print("Proj4 String:", crs.toProj4()) # check whether it's geographic or projected coordinate system print("Is geographic:", crs.geographicFlag()) # check type of map units in this CRS (values defined in QGis::units enum) print("Map units:", crs.mapUnits()) print("-----------------------------------------------\n\n") wkt = '''GEOGCS["WGS84", DATUM["WGS84", SPHEROID["WGS84", 6378137.0, 298.257223563]], PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH]]''' crs = QgsCoordinateReferenceSystem(wkt) print("Valid: ", crs.isValid()) print("QGIS CRS ID:", crs.srsid()) print("EPSG ID:", crs.authid()) print("Description:", crs.description()) print("Projection Acronym:", crs.projectionAcronym()) print("Ellipsoid Acronym:", crs.ellipsoidAcronym()) print("Proj4 String:", crs.toProj4()) # check whether it's geographic or projected coordinate system
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. reseau = self.parameterAsVectorLayer(parameters, self.RESEAU, context) fenetre = self.parameterAsExtent(parameters, self.FENETRE, context) cout_i = QgsExpression( self.parameterAsExpression(parameters, self.COUT_I, context)) cout_j = QgsExpression( self.parameterAsExpression(parameters, self.COUT_J, context)) sens = QgsExpression( self.parameterAsExpression(parameters, self.SENS, context)) diffusion = QgsExpression( self.parameterAsExpression(parameters, self.DIFFUSION, context)) traversabilite = QgsExpression( self.parameterAsExpression(parameters, self.TRAVERSABILITE, context)) nb_pixels_x = self.parameterAsInt(parameters, self.NB_PIXELS_X, context) nb_pixels_y = self.parameterAsInt(parameters, self.NB_PIXELS_Y, context) taille_pixel_x = self.parameterAsDouble(parameters, self.TAILLE_PIXEL_X, context) taille_pixel_y = self.parameterAsDouble(parameters, self.TAILLE_PIXEL_Y, context) decimales = self.parameterAsInt(parameters, self.DECIMALES, context) rayon = self.parameterAsDouble(parameters, self.RAYON, context) vitesse_diffusion = QgsExpression( self.parameterAsExpression(parameters, self.VITESSE_DIFFUSION, context)) intraversable = self.parameterAsBool(parameters, self.INTRAVERSABLE, context) valeurs_individuelles = QgsExpression( self.parameterAsExpression(parameters, self.IND_VALUES, context)) resultat = self.parameterAsOutputLayer( parameters, self.RESULTAT, context ) # Compute the number of steps to display within the progress bar and poles = {} formule_cout_i = self.createExpressionContext(parameters, context) cout_i.prepare(formule_cout_i) formule_cout_j = self.createExpressionContext(parameters, context) cout_j.prepare(formule_cout_j) formule_sens = self.createExpressionContext(parameters, context) sens.prepare(formule_sens) formule_diffusion = self.createExpressionContext(parameters, context) diffusion.prepare(formule_diffusion) formule_traversabilite = self.createExpressionContext( parameters, context) traversabilite.prepare(formule_traversabilite) formule_vitesse_diffusion = self.createExpressionContext( parameters, context) vitesse_diffusion.prepare(formule_vitesse_diffusion) formule_valeurs_individuelles = self.createExpressionContext( parameters, context) valeurs_individuelles.prepare(formule_valeurs_individuelles) crsSrc = QgsCoordinateReferenceSystem('EPSG:' + str(reseau.crs().postgisSrid())) dist_unit = QgsUnitTypes.fromUnitToUnitFactor( crsSrc.mapUnits(), QgsUnitTypes.DistanceMeters) rayon = rayon / dist_unit grille = numpy.array([[-9999.0] * nb_pixels_y] * nb_pixels_x) grille_distance = numpy.array([[1e38] * nb_pixels_y] * nb_pixels_x) grille_ind = numpy.array([['0'] * nb_pixels_y] * nb_pixels_x, dtype='<U25') rep = os.path.dirname(resultat) a = fenetre.asWktCoordinates().split(',') fenetre2 = fenetre #QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3])) p1 = a[0].split() p2 = a[1].split() ll = (float(p1[0]), float(p1[1])) hauteur = float(p2[1]) - float(p1[1]) largeur = float(p2[0]) - float(p1[0]) if not (taille_pixel_x <= 0): nb_pixels_x = int(largeur / taille_pixel_x) else: taille_pixel_x = float(largeur / nb_pixels_x) if not (taille_pixel_y <= 0): nb_pixels_y = int(hauteur / taille_pixel_y) else: taille_pixel_y = float(hauteur / nb_pixels_y) layer = reseau if layer.type() == QgsMapLayer.VectorLayer: if not layer == None: if layer.geometryType() == 1: simple = QgsSimplifyMethod() simple.setMethodType(QgsSimplifyMethod.PreserveTopology) simple.setTolerance( min(taille_pixel_x, taille_pixel_y) / 2) texte = diffusion.dump( ) + ' in (\'1\',\'2\',\'3\') and (' + cout_j.dump( ) + ' IS NOT NULL and ' + sens.dump( ) + ' in (\'1\',\'3\')) ' #request=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(texte).setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect) request = (QgsFeatureRequest().setFilterRect(fenetre2) ).setFilterExpression(texte) #req_intra=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(traversabilite.dump()+' in (\'1\',\'2\',\'3\')').setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect) req_intra = ( QgsFeatureRequest().setFilterRect(fenetre2) ).setFilterExpression(traversabilite.dump() + ' in (\'1\',\'2\',\'3\')') features = [f for f in layer.getFeatures(request)] if intraversable: features_intra = [ f for f in layer.getFeatures(req_intra) ] else: features_intra = [] for k, i in enumerate(features): formule_sens.setFeature(i) formule_cout_i.setFeature(i) formule_cout_j.setFeature(i) formule_vitesse_diffusion.setFeature(i) formule_diffusion.setFeature(i) formule_traversabilite.setFeature(i) formule_valeurs_individuelles.setFeature(i) var_diffusion = diffusion.evaluate(formule_diffusion) var_sens = sens.evaluate(formule_sens) var_traversabilite = traversabilite.evaluate( formule_traversabilite) ti = cout_i.evaluate(formule_cout_i) tj = cout_j.evaluate(formule_cout_j) var_ind = valeurs_individuelles.evaluate( formule_valeurs_individuelles) var_vitesse_diffusion = vitesse_diffusion.evaluate( formule_vitesse_diffusion) speed = 60 / (1000 * var_vitesse_diffusion) if var_sens in ['1', '2', '3']: geom = i.geometry() zone = geom.buffer(rayon, 12).boundingBox() deltax = int( (zone.xMinimum() - ll[0]) / taille_pixel_x) deltay = int( (zone.yMinimum() - ll[1]) / taille_pixel_y) dx = int(zone.width() / taille_pixel_x) dy = int(zone.height() / taille_pixel_y) l1 = geom.length() if geom.wkbType() == QgsWkbTypes.MultiLineString: geom_l = geom.asMultiPolyline() else: geom_l = geom.asPolyline() for p in range(dx): d2x = deltax + p for q in range(dy): d2y = deltay + q if 0 <= d2x < nb_pixels_x and 0 <= d2y < nb_pixels_y: pt1 = QgsGeometry.fromPointXY( QgsPointXY( ll[0] + (d2x + 0.5) * taille_pixel_x, ll[1] + (d2y + 0.5) * taille_pixel_y)) res = geom.closestSegmentWithContext( pt1.asPoint()) d = round(res[0], decimales) if d <= grille_distance[ d2x, d2y] and d < rayon * rayon: if d > 0 and l1 > 0: pt2 = res[1] #feedback.setProgressText(geom.asWkt()) if geom.wkbType( ) == QgsWkbTypes.MultiLineString: num_poly = -1 npts = 0 for k, id_poly in enumerate( geom_l): if res[2] < npts + len( id_poly): infos_poly = ( k, res[2]) else: npts += len( id_poly) #feedback.setProgressText(str(infos_poly[0])+"-"+str(infos_poly[1])+"-"+str(npts)) geoma = geom_l[infos_poly[ 0]][:(infos_poly[1] - npts)] + [pt2] else: geoma = geom_l[:res[2]] + [ pt2 ] #geoma=QgsGeometry(geom) #geoma.insertVertex(pt2[0],pt2[1],res[2]) l2 = QgsGeometry.fromPolylineXY( geoma).length() if res[2] == 0: pt3 = geom.vertexAt(res[2]) pt4 = geom.vertexAt( res[2] + 1) else: try: pt3 = geom.vertexAt( res[2] - 1) pt4 = geom.vertexAt( res[2]) except: print(res, geom_l) pt3 = geom_l[res[2] - 1] pt4 = geom_l[res[2]] p1 = pt1.asPoint() test_sens = (pt4.x() - pt3.x( )) * (p1.y() - pt2.y()) - ( p1.x() - pt2.x()) * ( pt4.y() - pt3.y()) if var_sens in [ '1', '3' ] and not tj == None: if (var_diffusion in ['1', '3'] and test_sens <= 0 ) or (var_diffusion in ['2', '3'] and test_sens >= 0): if not tj == None: if not ti == None: t = tj * ( l2 / l1 ) + ti * ( 1 - (l2 / l1) ) + math.sqrt( d ) * speed / dist_unit l3 = QgsGeometry.fromPolylineXY( [ pt1. asPoint( ), QgsPointXY( pt2 ) ]) result_test = False if l3 != None: if len(features_intra ) > 0: for intra in features_intra: if intra.geometry( ).intersects( l3 ): result_test = True break if result_test == False: if ( t < grille[d2x, d2y] and d == grille_distance[ d2x, d2y] ) or d < grille_distance[ d2x, d2y]: grille_distance[ d2x, d2y] = d grille[d2x, d2y] = t if var_ind not in poles: poles[ var_ind] = len( poles ) + 1 grille_ind[ d2x, d2y] = poles[ var_ind] sortie = os.path.splitext(resultat) fichier_grille = open(sortie[0] + sortie[1], 'w') fichier_grille.write( "NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n" .format(nb_pixels_x, nb_pixels_y, ll[0], ll[1], taille_pixel_x, taille_pixel_y)) fichier_grille2 = open(sortie[0] + "_dist" + sortie[1], 'w') fichier_grille2.write( "NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n" .format(nb_pixels_x, nb_pixels_y, ll[0], ll[1], taille_pixel_x, taille_pixel_y)) g1 = numpy.rot90(grille, 1) #g1=numpy.flipud(g1) g2 = numpy.rot90(grille_ind, 1) #g2=numpy.flipud(g2) for i in g1: fichier_grille.write(" ".join([str(ii) for ii in i]) + "\n") fichier_grille.close() for i in g2: fichier_grille2.write(" ".join([str(ii) for ii in i]) + "\n") fichier_grille2.close() fichier_prj = open(sortie[0] + ".prj", 'w') fichier2_prj = open(sortie[0] + "_dist.prj", 'w') fichier2_dict = open(sortie[0] + "_dist.dic", 'w') fichier_prj.write(layer.crs().toWkt()) fichier2_prj.write(layer.crs().toWkt()) fichier2_dict.write( json.dumps(dict(map(reversed, poles.items())))) fichier_prj.close() fichier2_prj.close() fichier2_dict.close() nom_sortie = os.path.basename(sortie[0]) rlayer = QgsRasterLayer(resultat, nom_sortie) return {self.RESULTAT: resultat}
def render(self, params): self.check_required_params(params) with change_directory(self.project_root): crs = QgsCoordinateReferenceSystem() crs.createFromSrid(params.get('srs')) img = QImage( QSize(*params.get('image_size')), QImage.Format_ARGB32_Premultiplied ) dpm = 1 / 0.00028 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) # set background color bgcolor = params.get('bgcolor') if params.get('transparent'): # fully transparent bgcolor.append(0) else: # fully opaque bgcolor.append(255) color = QColor(*bgcolor) img.fill(color) map_settings = QgsMapSettings() map_settings.setBackgroundColor(color) map_settings.setDestinationCrs(crs) map_settings.setCrsTransformEnabled(True) map_settings.setExtent(QgsRectangle(*params.get('bbox'))) map_settings.setOutputDpi(img.logicalDpiX()) map_settings.setOutputSize(img.size()) map_settings.setMapUnits(crs.mapUnits()) layers = params.get('layers') self.setTransparencies(layers, params.get('transparencies')) map_settings.setLayers(layers) p = QPainter() p.begin(img) job = QgsMapRendererCustomPainterJob(map_settings, p) job.start() job.waitForFinished() map_buffer = QBuffer() map_buffer.open(QIODevice.ReadWrite) if params.get('image_format') == 'jpeg': img.save(map_buffer, 'JPEG') elif params.get('image_format') == 'png8': png8 = img.convertToFormat(QImage.Format_Indexed8) png8.save(map_buffer, "PNG") else: img.save(map_buffer, 'PNG') # clean up p.end() map_buffer.close() return map_buffer.data()
class CoordinateCapture: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'CoordinateCapture_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Coordinate Capture') # TODO: We are going to let the user set this up in a future iteration # print "** INITIALIZING CoordinateCapture" self.pluginIsActive = False self.dockwidget = None self.crs = QgsCoordinateReferenceSystem("EPSG:4326") self.transform = QgsCoordinateTransform() self.transform.setDestinationCrs(self.crs) if self.crs.mapUnits() == QgsUnitTypes.DistanceDegrees: self.userCrsDisplayPrecision = 5 else: self.userCrsDisplayPrecision = 3 self.canvasCrsDisplayPrecision = None self.iface.mapCanvas().destinationCrsChanged.connect(self.setSourceCrs) self.setSourceCrs() self.mapTool = CoordinateCaptureMapTool(self.iface.mapCanvas()) self.mapTool.mouseMoved.connect(self.mouseMoved) self.mapTool.mouseClicked.connect(self.mouseClicked) # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('CoordinateCapture', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.iface.addVectorToolBarIcon(action) if add_to_menu: self.iface.addPluginToVectorMenu( "", action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/coordinate_capture/coordinate_capture.png' self.add_action( icon_path, text=self.tr(u'Coordinate Capture'), callback=self.run, parent=self.iface.mainWindow()) # -------------------------------------------------------------------------- def onClosePlugin(self): """Cleanup necessary items here when plugin dockwidget is closed""" # print "** CLOSING CoordinateCapture" # disconnects self.dockwidget.closingPlugin.disconnect(self.onClosePlugin) # remove this statement if dockwidget is to remain # for reuse if plugin is reopened # Commented next statement since it causes QGIS crashe # when closing the docked window: # self.dockwidget = None self.pluginIsActive = False self.mapTool.deactivate() def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" # print "** UNLOAD CoordinateCapture" self.mapTool.deactivate() for action in self.actions: self.iface.removePluginVectorMenu( "", action) self.iface.removeVectorToolBarIcon(action) # -------------------------------------------------------------------------- def run(self): """Run method that loads and starts the plugin""" if not self.pluginIsActive: self.pluginIsActive = True # print "** STARTING CoordinateCapture" # dockwidget may not exist if: # first run of plugin # removed on close (see self.onClosePlugin method) if self.dockwidget == None: # Create the dockwidget (after translation) and keep reference self.dockwidget = CoordinateCaptureDockWidget() self.dockwidget.userCrsToolButton.clicked.connect(self.setCrs) self.dockwidget.captureButton.clicked.connect(self.startCapturing) # connect to provide cleanup on closing of dockwidget self.dockwidget.closingPlugin.connect(self.onClosePlugin) # show the dockwidget # TODO: fix to allow choice of dock location self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockwidget) self.dockwidget.show() def setCrs(self): selector = QgsProjectionSelectionDialog(self.iface.mainWindow()) selector.setCrs(self.crs) if selector.exec(): self.crs = selector.crs() self.transform.setDestinationCrs(self.crs) if self.crs.mapUnits() == QgsUnitTypes.DistanceDegrees: self.userCrsDisplayPrecision = 5 else: self.userCrsDisplayPrecision = 3 def setSourceCrs(self): self.transform.setSourceCrs(self.iface.mapCanvas().mapSettings().destinationCrs()) if self.iface.mapCanvas().mapSettings().destinationCrs().mapUnits() == QgsUnitTypes.DistanceDegrees: self.canvasCrsDisplayPrecision = 5 else: self.canvasCrsDisplayPrecision = 3 def mouseMoved(self, point: QgsPointXY): if self.dockwidget.trackMouseButton.isChecked(): self.update(point) def mouseClicked(self, point: QgsPointXY): self.dockwidget.trackMouseButton.setChecked(False) self.update(point) def update(self, point: QgsPointXY): userCrsPoint = self.transform.transform(point) self.dockwidget.userCrsEdit.setText('{0:.{2}f}, {1:.{2}f}'.format(userCrsPoint.x(), userCrsPoint.y(), self.userCrsDisplayPrecision)) self.dockwidget.canvasCrsEdit.setText('{0:.{2}f}, {1:.{2}f}'.format(point.x(), point.y(), self.canvasCrsDisplayPrecision)) def startCapturing(self): self.iface.mapCanvas().setMapTool(self.mapTool)
def renderer(self): qgis = QgsApplication([], False) qgis.setPrefixPath(self.settings.get('path'), True) qgis.setMaxThreads(1) qgis.initQgis() while True: try: fndata, srs, render_size, extended, \ target_box, result = self.queue.get() layer = QgsVectorLayer(fndata, 'layer', 'ogr') crs = QgsCoordinateReferenceSystem(srs.id) layer.setCrs(crs) settings = QgsMapSettings() settings.setLayers([layer.id()]) settings.setFlag(QgsMapSettings.DrawLabeling) settings.setFlag(QgsMapSettings.Antialiasing) settings.setCrsTransformEnabled(True) settings.setDestinationCrs(crs) settings.setMapUnits(crs.mapUnits()) settings.setOutputSize(QSize(*render_size)) settings.setExtent(QgsRectangle(*extended)) settings.setOutputImageFormat(QImage.Format_ARGB32) bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0)) settings.setBackgroundColor(bgcolor) settings.setOutputDpi(96) QgsMapLayerRegistry.instance().addMapLayer(layer) settings.setLayers([layer.id()]) # Создаем QImage руками чтобы можно было использовать # QgsMapRendererCustomPainterJob. Остальные не позволяют # обойти баг с рисованием поверх старого. img = QImage(settings.outputSize(), QImage.Format_ARGB32) # Эти костыли нужны для того, чтобы корректно рисовались # слои на прозрачном фоне, без этого получается каша. img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255))) img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0))) # DPI должно быть таким же как в settings, иначе ошибка. В QImage # разрешение указывается в точках на метр по каждой оси. dpm = settings.outputDpi() / 25.4 * 1000 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) painter = QPainter(img) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() # Преобразование QImage в PIL ba = QByteArray() bf = QBuffer(ba) bf.open(QIODevice.WriteOnly) img.save(bf, 'PNG') bf.close() buf = StringIO() buf.write(bf.data()) buf.seek(0) img = PIL.Image.open(buf) # Вырезаем нужный нам кусок изображения result.put(img.crop(target_box)) except Exception as e: self.logger.error(e.message) qgis.exitQgis()
def identify(self, params): self.check_required_params(params) feature_collections = [] with change_directory(self.project_root): crs = QgsCoordinateReferenceSystem() crs.createFromSrid(params.get('srs')) search_box = self._calcSearchBox( params.get('bbox'), params.get('image_size')[0], params.get('image_size')[1], params.get('click_point')[0], params.get('click_point')[1] ) # initialize mapRenderer and a rendering context in order to be # to check if a feature will actually be rendered # we don't want to return features that are not visible img = QImage(QSize( settings.SUNLUMO_GFI_BUFFER*2, settings.SUNLUMO_GFI_BUFFER*2), QImage.Format_ARGB32_Premultiplied ) dpm = 1 / 0.00028 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) mapRenderer = QgsMapRenderer() mapRenderer.clearLayerCoordinateTransforms() mapRenderer.setOutputSize(QSize( settings.SUNLUMO_GFI_BUFFER*2, settings.SUNLUMO_GFI_BUFFER*2), img.logicalDpiX() ) mapRenderer.setDestinationCrs(crs) mapRenderer.setProjectionsEnabled(True) mapUnits = crs.mapUnits() mapRenderer.setMapUnits(mapUnits) mapExtent = QgsRectangle(*search_box) mapRenderer.setExtent(mapExtent) renderContext = QgsRenderContext() renderContext.setExtent(mapRenderer.extent()) renderContext.setRasterScaleFactor(1.0) renderContext.setMapToPixel(mapRenderer.coordinateTransform()) renderContext.setRendererScale(mapRenderer.scale()) renderContext.setScaleFactor(mapRenderer.outputDpi() / 25.4) renderContext.setPainter(None) qfr = QgsFeatureRequest() search_rectangle = QgsRectangle(*search_box) qfr.setFilterRect(search_rectangle) for q_layer in params.get('query_layers'): layer = self.layerRegistry.mapLayer(q_layer) if layer.type() == QgsMapLayer.RasterLayer: # skip raster layer processing continue # update layer fields (expressions, calculated, joined) layer.updateFields() scaleCalc = QgsScaleCalculator( (img.logicalDpiX() + img.logicalDpiY()) / 2, mapRenderer.destinationCrs().mapUnits() ) scaleDenom = scaleCalc.calculate(mapExtent, img.width()) # skip the layer if it's not visible at the current map scale if layer.hasScaleBasedVisibility(): if not(layer.minimumScale() < scaleDenom < layer.maximumScale()): continue # check if features actually intersect search rectangle intersected_features = self._intersectedFeatures( layer.getFeatures(qfr), search_rectangle ) # visible features generator visible_features = self._visibleFeatures( layer, renderContext, intersected_features ) layer_features = [featureToGeoJSON( feature.id(), feature.geometry(), self._collectAttributes(layer, feature) ) for feature in visible_features ] feature_collections.append(layer_features) return writeGeoJSON(chain(*feature_collections))
dpi = args.dpi img = QImage(iwidth, iheight, QImage.Format_RGB32) img.setDotsPerMeterX(dpi / 25.4 * 1000) img.setDotsPerMeterY(dpi / 25.4 * 1000) img.fill(qRgb(255, 255, 255)) dpi = img.logicalDpiX() print("Image DPI: %d" % dpi) render.setOutputSize(QSize(img.width(), img.height()), dpi) render.setDestinationCrs(crs) render.setProjectionsEnabled(True) render.setMapUnits(crs.mapUnits()) render.setExtent(extent) print("Scale: %f" % render.scale()) painter = QPainter(img) painter.setRenderHint(QPainter.Antialiasing) render.render(painter) painter.end() ba = QByteArray() bf = QBuffer(ba) bf.open(QIODevice.WriteOnly) img.save(bf, 'PNG') bf.close()