コード例 #1
0
class GtoWidgetQgisLayers(QWidget):
    def __init__(self, gtoObj, parent=None):
        super(GtoWidgetQgisLayers, self).__init__(parent)
        # QWidgetAction.__init__(self,parent)
        self.gtomain = gtoObj.gtomain
        self.info = self.gtomain.info
        self.iface = self.gtomain.iface
        self.canvas = self.iface.mapCanvas()
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)

        self.qgsLayers = QgsMapLayerComboBox()
        self.qgsLayers.setMinimumContentsLength(25)
        self.qgsLayers.setMinimumWidth(300)
        self.qgsLayers.setCurrentIndex(-1)
        self.qgsLayers.setFilters(QgsMapLayerProxyModel.VectorLayer)
        #signals
        self.canvas.currentLayerChanged.connect(self.qgsLayers.setLayer)
        self.qgsLayers.layerChanged.connect(self.layer_changed)
        self.canvas.selectionChanged.connect(self.selection_changed)
        # ui
        lay = QHBoxLayout(self)
        self.caption = 'Layer: ({0})'
        self.lblLayer = QLabel('Layer:')
        self.lblLayer.setToolTip("Aktiver Layer (selected features)")
        lay.addWidget(self.lblLayer)
        lay.addWidget(self.qgsLayers)
        self.setLayout(lay)
        # help QgsMapLayerComboBox ..:O
        self.timer = QTimer()
        self.timer.singleShot(100, self._setLayer)

    def selection_changed(self, layer):
        try:
            selcount = len(layer.selectedFeatureIds())
            self.lblLayer.setText(self.caption.format(selcount))
        except Exception as e:
            self.info.err(e)

    def layer_changed(self, layer):
        try:
            if layer is not None:
                self.selection_changed(layer)
                self.iface.setActiveLayer(layer)
                ml = QgsProject.instance().layerTreeRoot().findLayer(
                    layer.id())
                if ml is not None:
                    ml.setItemVisibilityCheckedParentRecursive(True)
        except Exception as e:
            self.info.err(e)

    def _setLayer(self):
        try:
            layer = self.iface.activeLayer()
            if layer is not None:
                self.qgsLayers.setLayer(layer)
        except Exception as e:
            self.info.err(e)
コード例 #2
0
class GtoWidgetActiveLayer(QWidget):
    def __init__(self, gtomain, parent=None):
        super(GtoWidgetActiveLayer, self).__init__(parent)
        # QWidgetAction.__init__(self,parent)
        self.iface = gtomain.iface
        self.info = gtomain.info
        self.canvas = self.iface.mapCanvas()
        # ui
        lay = QHBoxLayout(self)
        self.lblCaption = QLabel('Layer:')
        self.lblCaption.setToolTip("Aktiver Layer (selected features)")
        lay.addWidget(self.lblCaption)

        self.lblLayer = QLabel()
        self.qgsLayers = QgsMapLayerComboBox()
        self.qgsLayers.setCurrentIndex(-1)
        self.qgsLayers.setFilters(QgsMapLayerProxyModel.VectorLayer)

        lay.addWidget(self.lblLayer)

        self.setLayout(lay)

        # signals
        self.canvas.currentLayerChanged.connect(self.layer_changed)
        self.canvas.selectionChanged.connect(self.selection_changed)
        # start
        self.layer_changed(self.iface.activeLayer())

    def selection_changed(self, layer):
        try:
            selcount = len(layer.selectedFeatureIds())
            self.lblLayer.setText(layer.name() + ' ({0})'.format(selcount))
        except Exception as e:
            self.info.err(e)

    def layer_changed(self, layer):
        try:
            self.selection_changed(layer)
        except Exception as e:
            self.info.err(e)
コード例 #3
0
# coding: utf-8
from PyQt4.QtGui import QDialog, QFormLayout
from qgis.gui import QgsFieldComboBox, QgsMapLayerComboBox

# Create dialog
new_dialog = QDialog()

# Add combobox for layer and field
map_layer_combo_box = QgsMapLayerComboBox()
map_layer_combo_box.setCurrentIndex(-1)
field_combo_box = QgsFieldComboBox()

# Create a form layout and add the two combobox
layout = QFormLayout()
layout.addWidget(map_layer_combo_box)
layout.addWidget(field_combo_box)

# Add signal event
map_layer_combo_box.layerChanged.connect(field_combo_box.setLayer)  # setLayer is a native slot function


def on_field_changed(fieldName):
    print(fieldName)
    print("Layer field changed")

field_combo_box.fieldChanged.connect(on_field_changed)

new_dialog.setLayout(layout)
new_dialog.show()  # To see possibility of this component, you need at least a layer opened
コード例 #4
0
ファイル: dialog.py プロジェクト: nextgis/qgis.connect_points
class Dialog(QtGui.QDialog):
    def __init__(
            self,
            curPointsLayerFrom,
            curPointsLayerTo,
            curFNIdFrom,
            curFNLink,
            curFNIdTo,
            curResultLayerName,
            parent=None):
        QtGui.QDialog.__init__(self, parent)

        self.resize(500, 200)

        self.setWindowTitle(QgisPlugin().pluginName)
        self.__mainLayout = QtGui.QVBoxLayout(self)
        self.__layout = QtGui.QGridLayout(self)

        l1 = QtGui.QLabel(self.tr(u"Point layer 'FROM'") + ":")
        l1.setSizePolicy(
            QtGui.QSizePolicy.Preferred,
            QtGui.QSizePolicy.Fixed
        )
        self.__layout.addWidget(l1, 0, 0)
        self.pointsLayerFrom = QgsMapLayerComboBox()
        self.pointsLayerFrom.setSizePolicy(
            QtGui.QSizePolicy.Expanding,
            QtGui.QSizePolicy.Fixed
        )
        self.pointsLayerFrom.setFilters(QgsMapLayerProxyModel.PointLayer)
        self.pointsLayerFrom.setEditable(True)
        # self.pointsLayerFrom.setEditText(curPointsLayerFrom)
        self.pointsLayerFrom.layerChanged.connect(self.choozeLayerFrom)
        self.__layout.addWidget(self.pointsLayerFrom, 0, 1)

        l2 = QtGui.QLabel(self.tr(u"Point layer 'TO'") + ":")
        l2.setSizePolicy(
            QtGui.QSizePolicy.Preferred,
            QtGui.QSizePolicy.Fixed
        )
        self.__layout.addWidget(l2, 1, 0)
        self.pointsLayerTo = QgsMapLayerComboBox()
        self.pointsLayerTo.setSizePolicy(
            QtGui.QSizePolicy.Expanding,
            QtGui.QSizePolicy.Fixed
        )
        self.pointsLayerTo.setFilters(QgsMapLayerProxyModel.PointLayer)
        self.pointsLayerTo.setEditable(True)
        # self.pointsLayerTo.setEditText(curPointsLayerTo)
        self.pointsLayerTo.layerChanged.connect(self.choozeLayerTo)
        self.__layout.addWidget(self.pointsLayerTo, 1, 1)

        self.__layout.addWidget(
            QtGui.QLabel(self.tr(u"Point 'FROM' id field") + ":"),
            2, 0
        )
        self.fnIdFrom = QgsFieldComboBox()
        self.fnIdFrom.setFilters(QgsFieldProxyModel.Int | QgsFieldProxyModel.LongLong)
        self.fnIdFrom.setEditable(True)
        # self.fnIdFrom.setEditText(curFNIdFrom)
        self.fnIdFrom.fieldChanged.connect(self.filedChooze)
        self.__layout.addWidget(self.fnIdFrom, 2, 1)

        self.__layout.addWidget(
            QtGui.QLabel(self.tr(u"Link field") + ":"),
            3, 0
        )
        self.fnLink = QgsFieldComboBox()
        self.fnLink.setFilters(QgsFieldProxyModel.Int | QgsFieldProxyModel.LongLong)
        self.fnLink.setEditable(True)
        # self.fnLink.setEditText(curFNLink)
        self.fnLink.fieldChanged.connect(self.filedChooze)
        self.__layout.addWidget(self.fnLink, 3, 1)

        self.__layout.addWidget(
            QtGui.QLabel(self.tr(u"Point 'TO' id field") + ":"), 4, 0)
        self.fnIdTo = QgsFieldComboBox()
        self.fnIdTo.setFilters(QgsFieldProxyModel.Int | QgsFieldProxyModel.LongLong)
        self.fnIdTo.setEditable(True)
        # self.fnIdTo.setEditText(curFNIdTo)
        self.fnIdTo.fieldChanged.connect(self.filedChooze)
        self.__layout.addWidget(self.fnIdTo, 4, 1)

        self.__layout.addWidget(
            QtGui.QLabel(self.tr(u"Save result in layer") + ":"),
            5, 0
        )
        self.linesLayer = QgsMapLayerComboBox()
        self.linesLayer.setSizePolicy(
            QtGui.QSizePolicy.Expanding,
            QtGui.QSizePolicy.Fixed
        )
        self.linesLayer.setFilters(QgsMapLayerProxyModel.LineLayer)
        self.linesLayer.setEditable(True)
        self.linesLayer.layerChanged.connect(self.choozeResultLayer)
        self.__layout.addWidget(self.linesLayer, 5, 1)

        # self.__layout4resultFileChoose = QtGui.QHBoxLayout()
        # self.leResultFilename = QtGui.QLineEdit(curResultFilename)
        # self.__layout4resultFileChoose.addWidget(self.leResultFilename)
        # self.pbChooseResultFilename = QtGui.QPushButton(u"Выбрать")
        # self.pbChooseResultFilename.released.connect(self.chooseResultFilename)
        # self.__layout4resultFileChoose.addWidget(self.pbChooseResultFilename)
        # self.__layout.addLayout(self.__layout4resultFileChoose, 6, 0, 2, 0)

        self.pointsLayerFrom.layerChanged.connect(self.fnIdFrom.setLayer)
        self.pointsLayerFrom.layerChanged.connect(self.fnLink.setLayer)

        self.pointsLayerTo.layerChanged.connect(self.fnIdTo.setLayer)

        self.__mainLayout.addLayout(self.__layout)

        self.__bbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok)
        self.__bbox.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
        self.__bbox.accepted.connect(self.accept)
        self.__mainLayout.addWidget(self.__bbox)

        self.fillControls(
            curPointsLayerFrom,
            curPointsLayerTo,
            curFNIdFrom,
            curFNLink,
            curFNIdTo,
            curResultLayerName
        )

    def fillControls(
        self,
        curPointsLayerFrom,
        curPointsLayerTo,
        curFNIdFrom,
        curFNLink,
        curFNIdTo,
        curResultLayerName
    ):
        QgisPlugin().plPrint("curPointsLayerFrom: " + curPointsLayerFrom)
        QgisPlugin().plPrint("curPointsLayerTo: " + curPointsLayerTo)
        QgisPlugin().plPrint("curFNIdFrom: " + curPointsLayerFrom)
        QgisPlugin().plPrint("curFNLink: " + curFNIdFrom)
        QgisPlugin().plPrint("curPointsLayerFrom: " + curFNLink)
        QgisPlugin().plPrint("curFNIdTo: " + curFNIdTo)
        QgisPlugin().plPrint("curResultLayerName: " + curResultLayerName)

        layerFrom = self.getQGISLayer(curPointsLayerFrom)
        layerTo = self.getQGISLayer(curPointsLayerTo)
        layerResult = self.getQGISLayer(curResultLayerName, True)

        if layerFrom is None:
            self.pointsLayerFrom.setCurrentIndex(-1)
            self.pointsLayerFrom.setEditText(curPointsLayerFrom)
        else:
            self.pointsLayerFrom.setLayer(layerFrom)

        if layerTo is None:
            self.pointsLayerTo.setCurrentIndex(-1)
            self.pointsLayerTo.setEditText(curPointsLayerTo)
        else:
            self.pointsLayerTo.setLayer(layerTo)

        if layerResult is None:
            self.linesLayer.setCurrentIndex(-1)
            self.linesLayer.setEditText(curResultLayerName)
        else:
            self.linesLayer.setLayer(layerResult)

        # self.fnIdFrom.clear()
        # self.fnLink.clear()
        # self.fnIdTo.clear()

        # self.fnIdFrom.setField(curFNIdFrom)
        self.fnIdFrom.setCurrentIndex(-1)
        self.fnIdFrom.setEditText(curFNIdFrom)
        # self.fnLink.setField(curFNLink)
        self.fnLink.setCurrentIndex(-1)
        self.fnLink.setEditText(curFNLink)
        # self.fnIdTo.setField(curFNIdTo)
        self.fnIdTo.setCurrentIndex(-1)
        self.fnIdTo.setEditText(curFNIdTo)

    def getQGISLayer(self, layerName, silent=False):
        if layerName is None:
            return
        if layerName == "":
            return

        layers = QgsMapLayerRegistry.instance().mapLayersByName(layerName)
        if len(layers) == 0:
            if silent is False:
                QgisPlugin().showMessageForUser(
                    self.tr(u"Layer with name '%s' not found!") % layerName,
                    QgsMessageBar.CRITICAL,
                    0
                )
            return None
        return layers[0]

    def choozeLayerFrom(self, qgsMapLayer):
        self.pointsLayerFrom.setEditText(qgsMapLayer.name())

    def choozeLayerTo(self, qgsMapLayer):
        self.pointsLayerTo.setEditText(qgsMapLayer.name())

    def choozeResultLayer(self, qgsMapLayer):
        self.linesLayer.setEditText(qgsMapLayer.name())

    def filedChooze(self, fieldName):
        self.sender().setEditText(fieldName)

    def chooseResultFilename(self):
        filename = QtGui.QFileDialog.getSaveFileName(
            self,
            self.tr(u"Choose file for save result"),
            self.curResultFilename
            # QtCore.QFileInfo(self.curResultFilename).absolutePath()
        )
        self.leResultFilename.setText(filename)

    def getSettings(self):
        return [
            self.pointsLayerFrom.currentText(),
            self.pointsLayerTo.currentText(),
            self.fnIdFrom.currentText(),
            self.fnLink.currentText(),
            self.fnIdTo.currentText(),
            self.linesLayer.currentText(),
        ]
コード例 #5
0
# coding: utf-8
from PyQt4.QtGui import QDialog, QFormLayout
from qgis.gui import (QgsFieldComboBox, QgsMapLayerComboBox,
                      QgsMapLayerProxyModel)

# Create dialog
new_dialog = QDialog()

# Add combobox for layer and field
map_layer_combo_box = QgsMapLayerComboBox()
map_layer_combo_box.setCurrentIndex(-1)
map_layer_combo_box.setFilters(QgsMapLayerProxyModel.VectorLayer)
field_combo_box = QgsFieldComboBox()

# Create a form layout and add the two combobox
layout = QFormLayout()
layout.addWidget(map_layer_combo_box)
layout.addWidget(field_combo_box)

# Add signal event
map_layer_combo_box.layerChanged.connect(field_combo_box.setLayer)  # setLayer is a native slot function


def on_field_changed(fieldName):
    print(fieldName)
    print("Layer field changed")

field_combo_box.fieldChanged.connect(on_field_changed)

new_dialog.setLayout(layout)
new_dialog.show()  # To see possibility of this component, you need at least a layer opened
コード例 #6
0
class NewProjectDialog(Dialog):
    '''
    dialog to select a layer and a name as inputs for creating a new project
    '''
    def setupUi(self):
        '''
        set up the user interface
        '''
        self.setMinimumWidth(500)
        self.setWindowTitle('Neues Projekt erstellen')

        project_manager = ProjectManager()
        self.project_names = [p.name for p in project_manager.projects]

        layout = QVBoxLayout(self)

        label = QLabel('Name des Projekts')
        self.name_edit = QLineEdit()
        self.name_edit.textChanged.connect(self.validate)
        layout.addWidget(label)
        layout.addWidget(self.name_edit)
        self.path = os.path.join(project_manager.settings.TEMPLATE_PATH,
                                 'projektflaechen')

        hlayout = QHBoxLayout(self)
        label = QLabel('Import der (Teil-)Flächen des Plangebiets')
        self.layer_combo = QgsMapLayerComboBox()
        self.layer_combo.setFilters(QgsMapLayerProxyModel.VectorLayer)

        self.source = None

        self.layer_combo.layerChanged.connect(self.set_layer)
        self.layer_combo.layerChanged.connect(self.validate)
        browse_button = QPushButton('...')
        browse_button.clicked.connect(self.browse_path)
        browse_button.setMaximumWidth(30)
        hlayout.addWidget(self.layer_combo)
        hlayout.addWidget(browse_button)
        layout.addWidget(label)
        layout.addLayout(hlayout)

        self.status_label = QLabel()
        layout.addWidget(self.status_label)

        spacer = QSpacerItem(
            20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        layout.addItem(spacer)

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)
        self.ok_button = buttons.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

        if len(self.layer_combo) > 0:
            self.set_layer(self.layer_combo.currentLayer())
        self.layer_combo.setCurrentIndex(0)

    def set_layer(self, layer: QgsVectorLayer = None):
        '''
        set layer as user selection

        Parameters
        ----------
        layer : QgsVectorLayer
            the selected layer
        '''
        if not layer:
            path = self.layer_combo.currentText()
            layer = QgsVectorLayer(path, 'testlayer_shp', 'ogr')
        self.source = layer
        self.validate()

    def browse_path(self):
        '''
        open dialog for user input of path to a shapefile and add it to the
        layer-combo
        '''
        path, sf = QFileDialog.getOpenFileName(
            self, 'Datei wählen', filter="Shapefile(*.shp)",
            directory=self.path)
        if path:
            self.path = os.path.split(path)[0]
            self.layer_combo.setAdditionalItems([str(path)])
            self.layer_combo.setCurrentIndex(self.layer_combo.count()-1)
            self.set_layer()

    def show(self) -> Tuple[bool, str, QgsVectorLayer]:
        '''
        show dialog and return selections made by user
        '''
        confirmed = self.exec_()
        if confirmed:
            return confirmed, self.name_edit.text(), self.source
        return False, None, None

    def validate(self):
        '''
        validate current input of name and layer, set the status label according
        to validation result
        '''
        name = str(self.name_edit.text())
        status_text = ''
        regexp = re.compile('[\\\/\:*?\"\'<>|]')
        error = False
        if name and regexp.search(name):
            status_text = ('Der Projektname darf keines der folgenden Zeichen '
                           'enthalten: \/:*?"\'<>|')
            error = True
        elif name in self.project_names:
            status_text = (
                f'Ein Projekt mit dem Namen {name} existiert bereits!\n'
                'Projektnamen müssen einzigartig sein.')
            error = True

        if self.source:
            if not self.source.isValid():
                status_text = 'Der Layer ist ungültig.'
                error = True
            elif not self.source.geometryType() == QgsWkbTypes.PolygonGeometry:
                status_text = 'Der Layer hat keine Polygongeometrie.'
                error = True

        self.status_label.setText(status_text)

        if not error and (name and self.source):
            self.ok_button.setEnabled(True)
        else:
            self.ok_button.setEnabled(False)
コード例 #7
0
class UAVPreparer:
    """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',
            'UAVPreparer_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)


        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&UAV Preparer')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'UAVPreparer')
        self.toolbar.setObjectName(u'UAVPreparer')

        # Declare variables
        self.outputfile = None

    # 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('UAVPreparer', 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
        """

        # Create the dialog (after translation) and keep reference
        self.dlg = UAVPreparerDialog()

        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.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/UAVPreparer/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(self.tr(u'Unmanned Aerial Vehicle Preparer')),
            callback=self.run,
            parent=self.iface.mainWindow())

        # Access the raster layer
        self.layerComboManagerDSM = QgsMapLayerComboBox(self.dlg.widgetDSM)
        self.layerComboManagerDSM.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.layerComboManagerDSM.setFixedWidth(175)
        self.layerComboManagerDSM.setCurrentIndex(-1)

        # Access the vector layer and an attribute field
        self.layerComboManagerPoint = QgsMapLayerComboBox(self.dlg.widgetPoint)
        self.layerComboManagerPoint.setCurrentIndex(-1)
        self.layerComboManagerPoint.setFilters(QgsMapLayerProxyModel.PointLayer)
        self.layerComboManagerPoint.setFixedWidth(175)
        self.layerComboManagerPointField = QgsFieldComboBox(self.dlg.widgetField)
        self.layerComboManagerPointField.setFilters(QgsFieldProxyModel.Numeric)
        self.layerComboManagerPoint.layerChanged.connect(self.layerComboManagerPointField.setLayer)

        # Set up of file save dialog
        self.fileDialog = QFileDialog()
        self.dlg.selectButton.clicked.connect(self.savefile)

        # Set up for the Help button
        self.dlg.helpButton.clicked.connect(self.help)

        # Set up for the Run button
        self.dlg.runButton.clicked.connect(self.start_progress)

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&UAV Preparer'),
                action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar


    def run(self):
        """Run method that performs all the real work"""
        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            pass

    def savefile(self):
        self.outputfile = self.fileDialog.getSaveFileName(None, "Save File As:", None, "Text Files (*.txt)")
        self.dlg.textOutput.setText(self.outputfile)

    def help(self):
        url = "https://github.com/nilswallenberg/UAVPreparer"
        webbrowser.open_new_tab(url)

    def start_progress(self):

        if not self.outputfile:
            QMessageBox.critical(None, "Error", "Specify an output file")
            return

        # Acquiring geodata and attributes
        dsm_layer = self.layerComboManagerDSM.currentLayer()
        if dsm_layer is None:
            QMessageBox.critical(None, "Error", "No valid raster layer is selected")
            return
        else:
            provider = dsm_layer.dataProvider()
            filepath_dsm = str(provider.dataSourceUri())

        point_layer = self.layerComboManagerPoint.currentLayer()
        if point_layer is None:
            QMessageBox.critical(None, "Error", "No valid vector point layer is selected")
            return
        else:
            vlayer = QgsVectorLayer(point_layer.source(), "point", "ogr")

        point_field = self.layerComboManagerPointField.currentField()
        idx = vlayer.fieldNameIndex(point_field)
        if idx == -1:
            QMessageBox.critical(None, "Error", "An attribute with unique fields must be selected")
            return


        ### main code ###

        # set radius
        rSquare = int(self.dlg.spinBox.value()) # half picture size

        # finding ID column
        idx = vlayer.fieldNameIndex(point_field)

        numfeat = vlayer.featureCount()
        result = np.zeros([numfeat, 4])

        self.dlg.progressBar.setRange(0, numfeat)
        counter = 0
        for feature in vlayer.getFeatures():
            self.dlg.progressBar.setValue (counter + 1)
            geom = feature.geometry()
            pp = geom.asPoint()
            x = pp[0]
            y = pp[1]
            gdalclipdsm = "gdalwarp -dstnodata -9999 -q -overwrite -te " + str(x - rSquare) + " " + str(y - rSquare) + \
                          " " + str(x + rSquare) + " " + str(y + rSquare) + " -of GTiff " + filepath_dsm + " " + self.plugin_dir + "/clipdsm.tif"

            #QMessageBox.critical(None, "Bla", gdalclipdsm)

            # call the gdal function
            si = subprocess.STARTUPINFO() # used to suppress cmd window
            si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            subprocess.call(gdalclipdsm, startupinfo=si)
            #subprocess.call(gdalclipdsm)

            dataset = gdal.Open(self.plugin_dir + "/clipdsm.tif")
            dsm_array = dataset.ReadAsArray().astype(np.float)

            result[counter, 0] = int(feature.attributes()[idx])
            result[counter, 1] = np.mean(dsm_array)
            result[counter, 2] = np.max(dsm_array)
            result[counter, 3] = np.min(dsm_array)
            counter += 1

        numformat = "%d " + "%6.2f " * 3
        headertext = "id mean max min"
        np.savetxt(self.outputfile, result, fmt=numformat, header=headertext, comments="", delimiter="/t")

        self.iface.messageBar().pushMessage("UAV Preparer. Operation successful!", level=QgsMessageBar.INFO, duration=5)
コード例 #8
0
class DSMGenerator:
    """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',
                                   'DSMGenerator_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Create the dialog (after translation) and keep reference
        self.dlg = DSMGeneratorDialog()

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&DSM Generator')
        # TODO: We are going to let the user set this up in a future iteration
        # self.toolbar = self.iface.addToolBar(u'DSMGenerator')
        # self.toolbar.setObjectName(u'DSMGenerator')

        # Declare variables
        self.OSMoutputfile = None
        self.DSMoutputfile = None

        if not (os.path.isdir(self.plugin_dir + '/temp')):
            os.mkdir(self.plugin_dir + '/temp')

        # Access the raster layer
        self.layerComboManagerDEM = QgsMapLayerComboBox(self.dlg.widgetRaster)
        self.layerComboManagerDEM.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.layerComboManagerDEM.setFixedWidth(175)
        self.layerComboManagerDEM.setCurrentIndex(-1)

        # Access the vector layer and an attribute field
        self.layerComboManagerPolygon = QgsMapLayerComboBox(
            self.dlg.widgetPolygon)
        self.layerComboManagerPolygon.setCurrentIndex(-1)
        self.layerComboManagerPolygon.setFilters(
            QgsMapLayerProxyModel.PolygonLayer)
        self.layerComboManagerPolygon.setFixedWidth(175)
        self.layerComboManagerPolygonField = QgsFieldComboBox(
            self.dlg.widgetField)
        self.layerComboManagerPolygonField.setFilters(
            QgsFieldProxyModel.Numeric)
        self.layerComboManagerPolygonField.setFixedWidth(150)
        self.layerComboManagerPolygon.layerChanged.connect(
            self.layerComboManagerPolygonField.setLayer)

        # Set up of DSM file save dialog
        self.DSMfileDialog = QFileDialog()
        self.dlg.saveButton.clicked.connect(self.savedsmfile)

        # Set up of OSM polygon file save dialog
        self.OSMfileDialog = QFileDialog()
        self.dlg.savePolygon.clicked.connect(self.saveosmfile)

        # Set up for the Help button
        self.dlg.helpButton.clicked.connect(self.help)

        # Set up for the Close button
        self.dlg.closeButton.clicked.connect(self.resetPlugin)

        # Set up for the Run button
        self.dlg.runButton.clicked.connect(self.start_progress)

        # Set up extent
        self.dlg.canvasButton.toggled.connect(self.checkbox_canvas)
        # self.dlg.layerButton.toggled.connect(self.checkbox_layer)

        self.layerComboManagerExtent = QgsMapLayerComboBox(
            self.dlg.widgetLayerExtent)
        self.layerComboManagerExtent.setCurrentIndex(-1)
        self.layerComboManagerExtent.layerChanged.connect(self.checkbox_layer)
        self.layerComboManagerExtent.setFixedWidth(175)

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        return QCoreApplication.translate('DSMGenerator', 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):

        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.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        icon_path = ':/plugins/DSMGenerator/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'DSM Generator'),
                        callback=self.run,
                        parent=self.iface.mainWindow())

    def savedsmfile(self):
        self.DSMoutputfile = self.DSMfileDialog.getSaveFileName(
            None, "Save File As:", None, "Raster Files (*.tif)")
        self.dlg.DSMtextOutput.setText(self.DSMoutputfile)

    def saveosmfile(self):
        self.OSMoutputfile = self.OSMfileDialog.getSaveFileName(
            None, "Save File As:", None, "Shapefiles (*.shp)")
        self.dlg.OSMtextOutput.setText(self.OSMoutputfile)

    def checkbox_canvas(self):
        extent = self.iface.mapCanvas().extent()
        self.dlg.lineEditNorth.setText(str(extent.yMaximum()))
        self.dlg.lineEditSouth.setText(str(extent.yMinimum()))
        self.dlg.lineEditWest.setText(str(extent.xMinimum()))
        self.dlg.lineEditEast.setText(str(extent.xMaximum()))

    def checkbox_layer(self):
        dem_layer_extent = self.layerComboManagerExtent.currentLayer()
        if dem_layer_extent:
            extent = dem_layer_extent.extent()
            self.dlg.lineEditNorth.setText(str(extent.yMaximum()))
            self.dlg.lineEditSouth.setText(str(extent.yMinimum()))
            self.dlg.lineEditWest.setText(str(extent.xMinimum()))
            self.dlg.lineEditEast.setText(str(extent.xMaximum()))

    # Help button
    def help(self):
        url = "http://umep-docs.readthedocs.io/en/latest/pre-processor/Spatial%20Data%20DSM%20Generator.html"
        webbrowser.open_new_tab(url)

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(self.tr(u'&DSM Generator'), action)
            # self.iface.removeToolBarIcon(action)
        # remove the toolbar
        # del self.toolbar

    def run(self):
        self.dlg.show()
        self.dlg.exec_()

    def start_progress(self):
        import datetime
        start = datetime.datetime.now()
        # Check OS and dep
        if sys.platform == 'darwin':
            gdal_os_dep = '/Library/Frameworks/GDAL.framework/Versions/Current/Programs/'
        else:
            gdal_os_dep = ''

        if self.dlg.canvasButton.isChecked():
            # Map Canvas
            extentCanvasCRS = self.iface.mapCanvas()
            srs = extentCanvasCRS.mapSettings().destinationCrs()
            crs = str(srs.authid())
            # old_crs = osr.SpatialReference()
            # old_crs.ImportFromEPSG(int(crs[5:]))
            can_crs = QgsCoordinateReferenceSystem(int(crs[5:]))
            # can_wkt = extentCanvasCRS.mapRenderer().destinationCrs().toWkt()
            # can_crs = osr.SpatialReference()
            # can_crs.ImportFromWkt(can_wkt)
            # Raster Layer
            dem_layer = self.layerComboManagerDEM.currentLayer()
            dem_prov = dem_layer.dataProvider()
            dem_path = str(dem_prov.dataSourceUri())
            dem_raster = gdal.Open(dem_path)
            projdsm = osr.SpatialReference(wkt=dem_raster.GetProjection())
            projdsm.AutoIdentifyEPSG()
            projdsmepsg = int(projdsm.GetAttrValue('AUTHORITY', 1))
            dem_crs = QgsCoordinateReferenceSystem(projdsmepsg)

            # dem_wkt = dem_raster.GetProjection()
            # dem_crs = osr.SpatialReference()
            # dem_crs.ImportFromWkt(dem_wkt)
            if can_crs != dem_crs:
                extentCanvas = self.iface.mapCanvas().extent()
                extentDEM = dem_layer.extent()

                transformExt = QgsCoordinateTransform(can_crs, dem_crs)
                # transformExt = osr.CoordinateTransformation(can_crs, dem_crs)

                canminx = extentCanvas.xMinimum()
                canmaxx = extentCanvas.xMaximum()
                canminy = extentCanvas.yMinimum()
                canmaxy = extentCanvas.yMaximum()

                canxymin = transformExt.TransformPoint(canminx, canminy)
                canxymax = transformExt.TransformPoint(canmaxx, canmaxy)

                extDiffminx = canxymin[0] - extentDEM.xMinimum(
                )  # If smaller than zero = warning
                extDiffminy = canxymin[1] - extentDEM.yMinimum(
                )  # If smaller than zero = warning
                extDiffmaxx = canxymax[0] - extentDEM.xMaximum(
                )  # If larger than zero = warning
                extDiffmaxy = canxymax[0] - extentDEM.yMaximum(
                )  # If larger than zero = warning

                if extDiffminx < 0 or extDiffminy < 0 or extDiffmaxx > 0 or extDiffmaxy > 0:
                    QMessageBox.warning(
                        None,
                        "Warning! Extent of map canvas is larger than raster extent.",
                        "Change to an extent equal to or smaller than the raster extent."
                    )
                    return

        # Extent
        self.yMax = self.dlg.lineEditNorth.text()
        self.yMin = self.dlg.lineEditSouth.text()
        self.xMin = self.dlg.lineEditWest.text()
        self.xMax = self.dlg.lineEditEast.text()

        if not self.DSMoutputfile:
            QMessageBox.critical(None, "Error", "Specify a raster output file")
            return

        if self.dlg.checkBoxPolygon.isChecked() and not self.OSMoutputfile:
            QMessageBox.critical(None, "Error",
                                 "Specify an output file for OSM data")
            return

        # Acquiring geodata and attributes
        dem_layer = self.layerComboManagerDEM.currentLayer()
        if dem_layer is None:
            QMessageBox.critical(None, "Error",
                                 "No valid raster layer is selected")
            return
        else:
            provider = dem_layer.dataProvider()
            filepath_dem = str(provider.dataSourceUri())
        demRaster = gdal.Open(filepath_dem)
        dem_layer_crs = osr.SpatialReference()
        dem_layer_crs.ImportFromWkt(demRaster.GetProjection())
        self.dem_layer_unit = dem_layer_crs.GetAttrValue("UNIT")
        posUnits = [
            'metre', 'US survey foot', 'meter', 'm', 'ft', 'feet', 'foot',
            'ftUS', 'International foot'
        ]  # Possible units
        if not self.dem_layer_unit in posUnits:
            QMessageBox.critical(
                None, "Error",
                "Raster projection is not in metre or foot. Please reproject.")
            return

        polygon_layer = self.layerComboManagerPolygon.currentLayer()
        osm_layer = self.dlg.checkBoxOSM.isChecked()
        if polygon_layer is None and osm_layer is False:
            QMessageBox.critical(None, "Error",
                                 "No valid building height layer is selected")
            return
        elif polygon_layer:
            vlayer = QgsVectorLayer(polygon_layer.source(), "buildings", "ogr")
            fileInfo = QFileInfo(polygon_layer.source())
            polygon_ln = fileInfo.baseName()

            polygon_field = self.layerComboManagerPolygonField.currentField()
            idx = vlayer.fieldNameIndex(polygon_field)
            flname = vlayer.attributeDisplayName(idx)

            if idx == -1:
                QMessageBox.critical(
                    None, "Error",
                    "An attribute with unique fields must be selected")
                return

        ### main code ###

        self.dlg.progressBar.setRange(0, 5)

        self.dlg.progressBar.setValue(1)

        if self.dlg.checkBoxOSM.isChecked():
            # TODO replace osr.CoordinateTransformation with QgsCoordinateTransform
            dem_original = gdal.Open(filepath_dem)
            dem_wkt = dem_original.GetProjection()
            ras_crs = osr.SpatialReference()
            ras_crs.ImportFromWkt(dem_wkt)
            rasEPSG = ras_crs.GetAttrValue("PROJCS|AUTHORITY", 1)
            if self.dlg.layerButton.isChecked():
                old_crs = ras_crs
            elif self.dlg.canvasButton.isChecked():
                canvasCRS = self.iface.mapCanvas()
                outputWkt = canvasCRS.mapRenderer().destinationCrs().toWkt()
                old_crs = osr.SpatialReference()
                old_crs.ImportFromWkt(outputWkt)

            wgs84_wkt = """
            GEOGCS["WGS 84",
                DATUM["WGS_1984",
                    SPHEROID["WGS 84",6378137,298.257223563,
                        AUTHORITY["EPSG","7030"]],
                    AUTHORITY["EPSG","6326"]],
                PRIMEM["Greenwich",0,
                    AUTHORITY["EPSG","8901"]],
                UNIT["degree",0.01745329251994328,
                    AUTHORITY["EPSG","9122"]],
                AUTHORITY["EPSG","4326"]]"""

            new_crs = osr.SpatialReference()
            new_crs.ImportFromWkt(wgs84_wkt)

            transform = osr.CoordinateTransformation(old_crs, new_crs)

            minx = float(self.xMin)
            miny = float(self.yMin)
            maxx = float(self.xMax)
            maxy = float(self.yMax)
            lonlatmin = transform.TransformPoint(minx, miny)
            lonlatmax = transform.TransformPoint(maxx, maxy)

            if ras_crs != old_crs:
                rasTrans = osr.CoordinateTransformation(old_crs, ras_crs)
                raslonlatmin = rasTrans.TransformPoint(float(self.xMin),
                                                       float(self.yMin))
                raslonlatmax = rasTrans.TransformPoint(float(self.xMax),
                                                       float(self.yMax))
                #else:
                #raslonlatmin = [float(self.xMin), float(self.yMin)]
                #raslonlatmax = [float(self.xMax), float(self.yMax)]

                self.xMin = raslonlatmin[0]
                self.yMin = raslonlatmin[1]
                self.xMax = raslonlatmax[0]
                self.yMax = raslonlatmax[1]

            # Make data queries to overpass-api
            urlStr = 'http://overpass-api.de/api/map?bbox=' + str(
                lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str(
                    lonlatmax[0]) + ',' + str(lonlatmax[1])
            osmXml = urllib.urlopen(urlStr).read()
            #print urlStr

            # Make OSM building file
            osmPath = self.plugin_dir + '/temp/OSM_building.osm'
            osmFile = open(osmPath, 'w')
            osmFile.write(osmXml)
            if os.fstat(osmFile.fileno()).st_size < 1:
                urlStr = 'http://api.openstreetmap.org/api/0.6/map?bbox=' + str(
                    lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str(
                        lonlatmax[0]) + ',' + str(lonlatmax[1])
                osmXml = urllib.urlopen(urlStr).read()
                osmFile.write(osmXml)
                #print 'Open Street Map'
                if os.fstat(osmFile.fileno()).st_size < 1:
                    QMessageBox.critical(None, "Error",
                                         "No OSM data available")
                    return

            osmFile.close()

            outputshp = self.plugin_dir + '/temp/'

            osmToShape = gdal_os_dep + 'ogr2ogr --config OSM_CONFIG_FILE "' + self.plugin_dir + '/osmconf.ini" -skipfailures -t_srs EPSG:' + str(
                rasEPSG
            ) + ' -overwrite -nlt POLYGON -f "ESRI Shapefile" "' + outputshp + '" "' + osmPath + '"'

            if sys.platform == 'win32':
                si = subprocess.STARTUPINFO()
                si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                subprocess.call(osmToShape, startupinfo=si)
            else:
                os.system(osmToShape)

            driver = ogr.GetDriverByName('ESRI Shapefile')
            driver.DeleteDataSource(outputshp + 'lines.shp')
            driver.DeleteDataSource(outputshp + 'multilinestrings.shp')
            driver.DeleteDataSource(outputshp + 'other_relations.shp')
            driver.DeleteDataSource(outputshp + 'points.shp')

            osmPolygonPath = outputshp + 'multipolygons.shp'
            vlayer = QgsVectorLayer(osmPolygonPath, 'multipolygons', 'ogr')
            polygon_layer = vlayer
            fileInfo = QFileInfo(polygon_layer.source())
            polygon_ln = fileInfo.baseName()

            def renameField(srcLayer, oldFieldName, newFieldName):
                ds = gdal.OpenEx(srcLayer.source(),
                                 gdal.OF_VECTOR | gdal.OF_UPDATE)
                ds.ExecuteSQL('ALTER TABLE {} RENAME COLUMN {} TO {}'.format(
                    srcLayer.name(), oldFieldName, newFieldName))
                srcLayer.reload()

            vlayer.startEditing()
            renameField(vlayer, 'building_l', 'bld_levels')
            renameField(vlayer, 'building_h', 'bld_hght')
            renameField(vlayer, 'building_c', 'bld_colour')
            renameField(vlayer, 'building_m', 'bld_materi')
            renameField(vlayer, 'building_u', 'bld_use')
            vlayer.commitChanges()

            vlayer.startEditing()
            vlayer.dataProvider().addAttributes(
                [QgsField('bld_height', QVariant.Double, 'double', 3, 2)])
            vlayer.updateFields()
            bld_lvl = vlayer.fieldNameIndex('bld_levels')
            hght = vlayer.fieldNameIndex('height')
            bld_hght = vlayer.fieldNameIndex('bld_hght')
            bld_height = vlayer.fieldNameIndex('bld_height')

            bldLvlHght = float(self.dlg.doubleSpinBoxBldLvl.value())
            illegal_chars = string.ascii_letters + "!#$%&'*+^_`|~:" + " "
            counterNone = 0
            counter = 0
            #counterWeird = 0
            for feature in vlayer.getFeatures():
                if feature[hght]:
                    try:
                        #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[hght])))
                        feature[bld_height] = float(
                            str(feature[hght]).translate(None, illegal_chars))
                    except:
                        counterNone += 1
                elif feature[bld_hght]:
                    try:
                        #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[bld_hght])))
                        feature[bld_height] = float(
                            str(feature[bld_hght]).translate(
                                None, illegal_chars))
                    except:
                        counterNone += 1
                elif feature[bld_lvl]:
                    try:
                        #feature[bld_height] = float(re.sub("[^0-9]", "", str(feature[bld_lvl])))*bldLvlHght
                        feature[bld_height] = float(
                            str(feature[bld_lvl]).translate(
                                None, illegal_chars)) * bldLvlHght
                    except:
                        counterNone += 1
                else:
                    counterNone += 1
                vlayer.updateFeature(feature)
                counter += 1
            vlayer.commitChanges()
            flname = vlayer.attributeDisplayName(bld_height)
            counterDiff = counter - counterNone

        # Zonal statistics
        vlayer.startEditing()
        zoneStat = QgsZonalStatistics(vlayer, filepath_dem, "stat_", 1,
                                      QgsZonalStatistics.Mean)
        zoneStat.calculateStatistics(None)
        vlayer.dataProvider().addAttributes(
            [QgsField('height_asl', QVariant.Double)])
        vlayer.updateFields()
        e = QgsExpression('stat_mean + ' + flname)
        e.prepare(vlayer.pendingFields())
        idx = vlayer.fieldNameIndex('height_asl')

        for f in vlayer.getFeatures():
            f[idx] = e.evaluate(f)
            vlayer.updateFeature(f)

        vlayer.commitChanges()

        vlayer.startEditing()
        idx2 = vlayer.fieldNameIndex('stat_mean')
        vlayer.dataProvider().deleteAttributes([idx2])
        vlayer.updateFields()
        vlayer.commitChanges()

        self.dlg.progressBar.setValue(2)

        # Convert polygon layer to raster

        # Define pixel_size and NoData value of new raster
        pixel_size = self.dlg.spinBox.value()  # half picture size

        # Create the destination data source

        gdalrasterize = gdal_os_dep + 'gdal_rasterize -a ' + 'height_asl' + ' -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\
                        ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + ' -l "' + str(polygon_ln) + '" "' \
                         + str(polygon_layer.source()) + '" "' + self.plugin_dir + '/temp/clipdsm.tif"'

        # gdalclipdem = gdal_os_dep + 'gdalwarp -dstnodata -9999 -q -overwrite -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\
        #               ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + \
        #               ' -of GTiff ' + '"' + filepath_dem + '" "' + self.plugin_dir + '/temp/clipdem.tif"'

        # Rasterize
        if sys.platform == 'win32':
            si = subprocess.STARTUPINFO()
            si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            subprocess.call(gdalrasterize, startupinfo=si)
            # subprocess.call(gdalclipdem, startupinfo=si)
            gdal.Warp(self.plugin_dir + '/temp/clipdem.tif',
                      filepath_dem,
                      xRes=pixel_size,
                      yRes=pixel_size)
        else:
            os.system(gdalrasterize)
            # os.system(gdalclipdem)
            gdal.Warp(self.plugin_dir + '/temp/clipdem.tif',
                      filepath_dem,
                      xRes=pixel_size,
                      yRes=pixel_size)

        # Remove gdalwarp with gdal.Translate
        # bigraster = gdal.Open(filepath_dem)
        # bbox = (self.xMin, self.yMax, self.xMax, self.yMin)
        # gdal.Translate(self.plugin_dir + '/data/clipdem.tif', bigraster, projWin=bbox)

        self.dlg.progressBar.setValue(3)

        # Adding DSM to DEM
        # Read DEM
        dem_raster = gdal.Open(self.plugin_dir + '/temp/clipdem.tif')
        dem_array = np.array(dem_raster.ReadAsArray().astype(np.float))
        dsm_raster = gdal.Open(self.plugin_dir + '/temp/clipdsm.tif')
        dsm_array = np.array(dsm_raster.ReadAsArray().astype(np.float))

        indx = dsm_array.shape
        for ix in range(0, int(indx[0])):
            for iy in range(0, int(indx[1])):
                if int(dsm_array[ix, iy]) == 0:
                    dsm_array[ix, iy] = dem_array[ix, iy]

        if self.dlg.checkBoxPolygon.isChecked():
            vlayer.startEditing()
            idxHght = vlayer.fieldNameIndex('height_asl')
            idxBld = vlayer.fieldNameIndex('building')
            features = vlayer.getFeatures()
            #for f in vlayer.getFeatures():
            for f in features:
                geom = f.geometry()
                posUnitsMetre = ['metre', 'meter', 'm']  # Possible metre units
                posUnitsFt = [
                    'US survey foot', 'ft', 'feet', 'foot', 'ftUS',
                    'International foot'
                ]  # Possible foot units
                if self.dem_layer_unit in posUnitsMetre:
                    sqUnit = 1
                elif self.dem_layer_unit in posUnitsFt:
                    sqUnit = 10.76
                if int(geom.area()) > 50000 * sqUnit:
                    vlayer.deleteFeature(f.id())

                #if not f[idxHght]:
                #vlayer.deleteFeature(f.id())
                #elif not f[idxBld]:
                #vlayer.deleteFeature(f.id())
            vlayer.updateFields()
            vlayer.commitChanges()
            QgsVectorFileWriter.writeAsVectorFormat(vlayer,
                                                    str(self.OSMoutputfile),
                                                    "UTF-8", None,
                                                    "ESRI Shapefile")

        else:
            vlayer.startEditing()
            idx3 = vlayer.fieldNameIndex('height_asl')
            vlayer.dataProvider().deleteAttributes([idx3])
            vlayer.updateFields()
            vlayer.commitChanges()

        self.dlg.progressBar.setValue(4)

        # Save raster
        def saveraster(
            gdal_data, filename, raster
        ):  # gdal_data = raster extent, filename = output filename, raster = numpy array (raster to be saved)
            rows = gdal_data.RasterYSize
            cols = gdal_data.RasterXSize

            outDs = gdal.GetDriverByName("GTiff").Create(
                filename, cols, rows, int(1), gdal.GDT_Float32)
            outBand = outDs.GetRasterBand(1)

            # write the data
            outBand.WriteArray(raster, 0, 0)
            # flush data to disk, set the NoData value and calculate stats
            outBand.FlushCache()
            outBand.SetNoDataValue(-9999)

            # georeference the image and set the projection
            outDs.SetGeoTransform(gdal_data.GetGeoTransform())
            outDs.SetProjection(gdal_data.GetProjection())

        saveraster(dsm_raster, self.DSMoutputfile, dsm_array)

        # Load result into canvas
        rlayer = self.iface.addRasterLayer(self.DSMoutputfile)

        # Trigger a repaint
        if hasattr(rlayer, "setCacheImage"):
            rlayer.setCacheImage(None)
        rlayer.triggerRepaint()

        self.dlg.progressBar.setValue(5)

        #runTime = datetime.datetime.now() - start

        if self.dlg.checkBoxOSM.isChecked():
            QMessageBox.information(
                self.dlg, 'DSM Generator', 'Operation successful! ' +
                str(counterDiff) + ' building polygons out of ' +
                str(counter) + ' contained height values.')
            #self.iface.messageBar().pushMessage("DSM Generator. Operation successful! " + str(counterDiff) + " buildings out of " + str(counter) + " contained height values.", level=QgsMessageBar.INFO, duration=5)
        else:
            #self.iface.messageBar().pushMessage("DSM Generator. Operation successful!", level=QgsMessageBar.INFO, duration=5)
            QMessageBox.information(self.dlg, 'DSM Generator',
                                    'Operation successful!')

        self.resetPlugin()

        #print "finished run: %s\n\n" % (datetime.datetime.now() - start)

    def resetPlugin(self):  # Reset plugin
        self.dlg.canvasButton.setAutoExclusive(False)
        self.dlg.canvasButton.setChecked(False)
        self.dlg.layerButton.setAutoExclusive(False)
        self.dlg.layerButton.setChecked(False)
        self.dlg.checkBoxOSM.setCheckState(0)
        self.dlg.checkBoxPolygon.setCheckState(0)

        # Extent
        self.layerComboManagerExtent.setCurrentIndex(-1)
        self.dlg.lineEditNorth.setText("")
        self.dlg.lineEditSouth.setText("")
        self.dlg.lineEditWest.setText("")
        self.dlg.lineEditEast.setText("")

        # Output boxes
        self.dlg.OSMtextOutput.setText("")
        self.dlg.DSMtextOutput.setText("")

        # Input raster
        self.layerComboManagerDEM.setCurrentIndex(-1)

        # Input polygon
        self.layerComboManagerPolygon.setCurrentIndex(-1)

        # Progress bar
        self.dlg.progressBar.setValue(0)

        # Spin boxes
        self.dlg.spinBox.setValue(2)
        self.dlg.doubleSpinBoxBldLvl.setValue(2.5)
コード例 #9
0
ファイル: uav_preparer.py プロジェクト: biglimp/UAVPreparer
class UAVPreparer:
    """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',
                                   'UAVPreparer_{}.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'&UAV Preparer')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None

        # Declare variables
        self.outputfile = None

    # 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('UAVPreparer', 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:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/uav_preparer/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'UAV Preparer'),
                        callback=self.run,
                        parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(self.tr(u'&UAV Preparer'), action)
            self.iface.removeToolBarIcon(action)

    def run(self):
        """Run method that performs all the real work"""
        # Create the dialog with elements (after translation) and keep reference
        # Only create GUI ONCE in callback, so that it will only load when the plugin is started
        if self.first_start == True:
            self.first_start = False
            self.dlg = UAVPreparerDialog()

        # Access the raster layer
        self.layerComboManagerDSM = QgsMapLayerComboBox(self.dlg.widgetDSM)
        self.layerComboManagerDSM.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.layerComboManagerDSM.setFixedWidth(175)
        self.layerComboManagerDSM.setCurrentIndex(-1)

        # Access the vector layer and an attribute field
        self.layerComboManagerPoint = QgsMapLayerComboBox(
            self.dlg.widgetPointLayer)
        self.layerComboManagerPoint.setCurrentIndex(-1)
        self.layerComboManagerPoint.setFilters(
            QgsMapLayerProxyModel.PointLayer)
        self.layerComboManagerPoint.setFixedWidth(175)
        self.layerComboManagerPointField = QgsFieldComboBox(
            self.dlg.widgetField)
        self.layerComboManagerPointField.setFilters(QgsFieldProxyModel.Numeric)
        self.layerComboManagerPoint.layerChanged.connect(
            self.layerComboManagerPointField.setLayer)

        # Set up of file save dialog
        self.fileDialog = QFileDialog()
        self.dlg.pushButtonSave.clicked.connect(self.savefile)

        # Set up for the Help button
        self.dlg.helpButton.clicked.connect(self.help)

        # Set up for the Run button
        self.dlg.runButton.clicked.connect(self.start_progress)

        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            pass

    def savefile(self):
        self.outputfile = self.fileDialog.getSaveFileName(
            None, "Save File As:", None, "Text Files (*.txt)")
        self.dlg.textOutput.setText(self.outputfile[0])

    def help(self):
        url = "https://github.com/biglimp/UAVPreparer"
        webbrowser.open_new_tab(url)

    def start_progress(self):
        if not self.outputfile:
            QMessageBox.critical(None, "Error", "Specify an output file")
            return

        # Acquiring geodata and attributes
        dsm_layer = self.layerComboManagerDSM.currentLayer()
        if dsm_layer is None:
            QMessageBox.critical(None, "Error",
                                 "No valid raster layer is selected")
            return
        else:
            provider = dsm_layer.dataProvider()
            filepath_dsm = str(provider.dataSourceUri())

        point_layer = self.layerComboManagerPoint.currentLayer()
        if point_layer is None:
            QMessageBox.critical(None, "Error",
                                 "No valid vector point layer is selected")
            return
        else:
            vlayer = QgsVectorLayer(point_layer.source(), "polygon", "ogr")

        point_field = self.layerComboManagerPointField.currentField()
        idx = vlayer.fields().indexFromName(point_field)
        if idx == -1:
            QMessageBox.critical(
                None, "Error",
                "An attribute with unique fields must be selected")
            return

        ### main code ###

        #  set radius
        r = 100  # half picture size

        numfeat = vlayer.featureCount()
        result = np.zeros([numfeat, 4])

        # load big raster
        bigraster = gdal.Open(filepath_dsm)
        filepath_tempdsm = self.plugin_dir + '/clipdsm.tif'

        self.dlg.progressBar.setRange(0, numfeat)
        i = 0
        for f in vlayer.getFeatures():
            self.dlg.progressBar.setValue(i + 1)
            # get the coordinate for the point
            y = f.geometry().centroid().asPoint().y()
            x = f.geometry().centroid().asPoint().x()

            bbox = (x - r, y + r, x + r, y - r)
            gdal.Translate(filepath_tempdsm, bigraster, projWin=bbox)
            data = gdal.Open(filepath_tempdsm)
            mat = np.array(data.ReadAsArray())

            result[i, 0] = int(f.attributes()[idx])
            result[i, 1] = np.mean(mat)
            result[i, 2] = np.max(mat)
            result[i, 3] = np.min(mat)

            i = i + 1

        # Saving to file
        numformat = '%d ' + '%6.2f ' * 3
        headertext = 'id mean max min'
        np.savetxt(self.outputfile[0],
                   result,
                   fmt=numformat,
                   delimiter=' ',
                   header=headertext)

        self.iface.messageBar().pushMessage(
            'UAV Preparer. Operation successful!',
            level=Qgis.Success,
            duration=5)
コード例 #10
0
ファイル: plugin.py プロジェクト: north-road/vertex_compare
class VertexComparePlugin(QObject):
    """QGIS Plugin Implementation."""
    def __init__(self, iface: QgisInterface):
        """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
        """
        super().__init__()
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QgsApplication.locale()
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   '{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        self.toolbar = None
        self.layer_combo = None
        self.actions = []
        self.dock = None
        self.vertex_highlighter = VertexHighlighterManager()
        self.selection_handler = SelectionHandler(self)
        self.show_vertices_action = None
        self.show_topology_action = None
        self.show_dock_action = None

    @staticmethod
    def tr(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('VertexCompare', message)

    def initProcessing(self):
        """Create the Processing provider"""

    def initGui(self):
        """Creates application GUI widgets"""
        self.initProcessing()

        self.dock = VertexDockWidget(self.iface.mapCanvas())
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.dock.setUserVisible(False)

        self.toolbar = QToolBar(self.tr('Vertex Compare Toolbar'))
        self.toolbar.setObjectName('vertexCompareToolbar')
        self.iface.addToolBar(self.toolbar)

        self.layer_combo = QgsMapLayerComboBox()
        self.layer_combo.setAllowEmptyLayer(True, self.tr('Disabled'))
        self.layer_combo.setFilters(QgsMapLayerProxyModel.PolygonLayer
                                    | QgsMapLayerProxyModel.LineLayer)
        self.layer_combo.setMinimumWidth(
            QFontMetrics(self.layer_combo.font()).width('x') * 40)
        self.layer_combo.setCurrentIndex(0)
        self.layer_combo.layerChanged.connect(self._set_layer)
        self.toolbar.addWidget(self.layer_combo)

        self.show_vertices_action = QAction(self.tr("Show Vertex Numbers"),
                                            self)
        self.show_vertices_action.setIcon(
            GuiUtils.get_icon('show_vertex_numbers.svg'))
        self.show_vertices_action.setCheckable(True)
        self.show_vertices_action.setEnabled(False)
        self.actions.append(self.show_vertices_action)
        self.toolbar.addAction(self.show_vertices_action)
        self.show_vertices_action.toggled.connect(
            self.vertex_highlighter.set_visible)

        self.show_topology_action = QAction(self.tr("Compare Vertices"), self)
        self.show_topology_action.setIcon(GuiUtils.get_icon('topology.svg'))
        self.show_topology_action.setCheckable(True)
        self.actions.append(self.show_topology_action)
        self.toolbar.addAction(self.show_topology_action)
        self.show_topology_action.toggled.connect(
            self.vertex_highlighter.set_topological)

        self.show_dock_action = QAction(self.tr('Show Vertices'),
                                        parent=self.toolbar)
        self.show_dock_action.setIcon(GuiUtils.get_icon('vertex_table.svg'))
        self.toolbar.addAction(self.show_dock_action)
        self.actions.append(self.show_dock_action)
        self.dock.setToggleVisibilityAction(self.show_dock_action)

        self.selection_handler.selection_changed.connect(
            self._selection_changed)
        self.dock.label_filter_changed.connect(self.vertex_highlighter.redraw)
        self.dock.vertex_symbol_changed.connect(self.vertex_highlighter.redraw)
        self.dock.vertex_text_format_changed.connect(
            self.vertex_highlighter.redraw)
        self.dock.selected_vertex_changed.connect(
            self.vertex_highlighter.set_selected_vertex)

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for a in self.actions:
            a.deleteLater()
        self.actions = []

        if self.toolbar is not None:
            self.toolbar.deleteLater()
            self.toolbar = None
        if self.dock is not None:
            self.dock.deleteLater()
            self.dock = None

    def _set_layer(self, layer: Optional[QgsVectorLayer]):
        """
        Triggered when the selected layer is changed
        """
        self.selection_handler.set_layer(layer)
        self.vertex_highlighter.set_layer(layer)
        self.show_vertices_action.setEnabled(layer is not None)
        if not self.show_vertices_action.isEnabled():
            self.show_vertices_action.setChecked(False)
        else:
            self.show_vertices_action.setChecked(True)

        self.dock.set_selection(
            layer,
            layer.selectedFeatureIds() if layer is not None else [])

    def _selection_changed(self, layer: Optional[QgsVectorLayer],
                           selection: List[int]):
        """
        Triggered when the watched layer's selection is changed
        """
        self.dock.set_selection(layer, selection)