def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        SELECTED_ONLY = self.getParameterValue(self.SELECTED_ONLY)
        kneighbors = int(self.getParameterValue(self.KNEIGHBORS))
        use_field = self.getParameterValue(self.METHOD) == 1
        field_name = self.getParameterValue(self.FIELD)

        # temporarily alter the processing environment
        old_setting = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
        ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, SELECTED_ONLY)

        # get properties of the field the grouping is based on
        if use_field:
            field = QgsField(field_name)
            field.setType(QVariant.String)
            field.setLength(255)
            index = layer.fieldNameIndex(field_name)
            field_type = layer.pendingFields()[index].type()
            if field_type == QVariant.Int:
                field.setType(QVariant.Int)
                field.setLength(20)
            elif field_type == QVariant.Double:
                field.setType(QVariant.Double)
                field.setLength(20)
                field.setPrecision(6)
            else:
                field.setType(QVariant.String)
                field.setLength(255)
            fields = [QgsField('clusterId', QVariant.Int, '', 20), field]
        else:
            # setup the fields of the output layer
            fields = [QgsField('clusterId', QVariant.Int, '', 20)]
            #fields.extend(layer.pendingFields().toList())

        # initialize writer
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QGis.WKBPoint, layer.crs())

        current = 0
        fid = 1

        if use_field:
            # get unique values of field denoted by index as filter conditions
            unique_values = layer.uniqueValues(index)
            total = 100.0 / float(layer.featureCount() * len(unique_values))

            for unique in unique_values:
                points = []
                first = True
                features = vector.features(layer)
                for in_feature in features:
                    value = in_feature[field_name]
                    if value == unique:
                        if first:
                            val = unique
                            first = False
                        points.extend(vector.extractPoints(QgsGeometry(in_feature.geometry())))
                    current += 1
                    progress.setPercentage(int(current * total))

                # A minimum of 3 points is necessary to proceed
                if len(points) >= 3:
                    out_feature = QgsFeature()
                    try:
                        clusters = SSNClusters(points, kneighbors).get_clusters()
                        for cluster in clusters.keys():
                            #mpoint = QgsGeometry.fromMultiPoint([QgsPoint(point[0], point[1]) for point in clusters[cluster]])
                            for member in clusters[cluster]:
                                point = QgsGeometry.fromPoint(QgsPoint(member[0], member[1]))

                                out_feature.setGeometry(point)
                                out_feature.setAttributes([fid, val])
                                writer.addFeature(out_feature)
                            fid += 1
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, 'Exception while computing clusters.')
                        raise GeoAlgorithmExecutionException('Exception while computing clusters.')
                    finally:
                        ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, old_setting)

        else:
            points = []
            features = vector.features(layer)
            total = 100.0 / float(len(features))
            for in_feature in features:
                ##points.append(in_feature.geometry().asPoint())
                points.extend(vector.extractPoints(QgsGeometry(in_feature.geometry())))
                current += 1
                progress.setPercentage(int(current * total))

            out_feature = QgsFeature()
            try:
                clusters = SSNClusters(points, kneighbors).get_clusters()
                for cluster in clusters.keys():
                    #mpoint = QgsGeometry.fromMultiPoint([QgsPoint(point[0], point[1]) for point in clusters[cluster]])
                    for member in clusters[cluster]:
                        point = QgsGeometry.fromPoint(QgsPoint(member[0], member[1]))

                        out_feature.setGeometry(point)
                        out_feature.setAttributes([cluster])
                        writer.addFeature(out_feature)
            except:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, 'Exception while computing clusters.')
                raise GeoAlgorithmExecutionException('Exception while computing clusters')
            finally:
                ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, old_setting)

        del writer
Beispiel #2
0
    def run(self):
        # set dialog widgets
        self.dlg.ls_layers.clear()
        self.dlg.buttonBox.button(QDialogButtonBox.Ok).setDisabled(True)
        has_selected_features = False

        # check if an active layer exists
        active_layer_name = ''
        if self.iface.activeLayer() is not None:
            active_layer_name = self.iface.activeLayer().name()

        # all vector layers get added to the list
        for index, layer in enumerate(self.iface.legendInterface().layers()):
            if layer.type() == QgsMapLayer.VectorLayer:
                # if there are selected features toggle has_selected_features
                if layer.selectedFeatureCount():
                    has_selected_features = True
                self.dlg.ls_layers.addItem(layer.name())
                # select the active layer by default
                if layer.name() == active_layer_name:
                    self.dlg.ls_layers.setCurrentRow(index)

        # if at least one vector layer has selected features enable checkbutton cb_selected_only
        if has_selected_features:
            self.dlg.cb_selected_only.setEnabled(True)
            self.dlg.cb_selected_only.setChecked(True)
        else:
            self.dlg.cb_selected_only.setChecked(False)
            self.dlg.cb_selected_only.setEnabled(False)

        # initialize cb_output
        # remember the layer being selected the last time
        last_index = self.dlg.cb_output.currentText()
        # populate the combo box with the polygon layers listed in the current legend
        self.set_output_layer_combobox(2, last_index)

        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()

        # See if OK was pressed
        if result == 1:
            geom = []
            # read selected list entries and get the map layer
            for layer_name in self.dlg.ls_layers.selectedItems():
                active_layer = QgsMapLayerRegistry.instance().mapLayersByName(
                    layer_name.text())[0]
                # get all or the currently selected features according to state of cb_selected_only
                # convert each feature to points
                if active_layer.selectedFeatureCount(
                ) and self.dlg.cb_selected_only.checkState():
                    for feat in active_layer.selectedFeatures():
                        geom.extend(extract_points(feat.geometry()))
                else:
                    for feat in active_layer.getFeatures():
                        geom.extend(extract_points(feat.geometry()))

            num_points = len(geom)
            if num_points == 0:
                return None

            # Send WARNING to the message bar to inform about a probably long running time
            if num_points > 1000:
                msg = self.msg_bar.createMessage(
                    u'Please be patient, processing of more then {} points may take a while'
                    .format(int(num_points)))
                self.msg_bar.pushWidget(msg, QgsMessageBar.WARNING, 2)

            # if more then 5000 points ask user to confirm
            if num_points > 5000:
                proceed = QMessageBox.question(
                    None, 'Please confirm', 'Do you really want to proceed?',
                    QMessageBox.Yes | QMessageBox.No)
                if proceed == QMessageBox.No:
                    QApplication.instance().setOverrideCursor(Qt.ArrowCursor)
                    return None

            # change cursor to inform user about ongoing processing
            QApplication.instance().setOverrideCursor(Qt.BusyCursor)

            # generate the hull geometry
            # process points with prior clustering
            hull_list = []
            if self.dlg.gb_clustering.isChecked():
                clusters = SSNClusters(
                    geom,
                    self.dlg.sb_neighborhood_list_size.value()).get_clusters()
                for cluster in clusters.keys():
                    the_hull = concave_hull(clusters[cluster],
                                            self.dlg.sb_neighbors.value())
                    if the_hull:
                        hull_list.append(
                            [as_polygon(the_hull),
                             len(clusters[cluster])])
            else:
                # process points without clustering
                the_hull = concave_hull(geom, self.dlg.sb_neighbors.value())
                hull_list.append([as_polygon(the_hull), len(geom)])

            # write hull geometries to output device
            success = self.create_output_feature(hull_list)

            # report result in QGIS message bar
            if success:
                msg = self.msg_bar.createMessage(
                    _translate(
                        'ConcaveHull',
                        '{} Concave hulls created successfully'.format(
                            int(len(hull_list))), None))
                self.msg_bar.pushWidget(msg, QgsMessageBar.INFO, 5)

            # reset cursor
            QApplication.instance().setOverrideCursor(Qt.ArrowCursor)

        return None
    def run(self):
        # set dialog widgets
        self.dlg.ls_layers.clear()
        self.dlg.buttonBox.button(QDialogButtonBox.Ok).setDisabled(True)
        has_selected_features = False

        # check if an active layer exists
        active_layer_name = ''
        if self.iface.activeLayer() is not None:
            active_layer_name = self.iface.activeLayer().name()

        # all vector layers get added to the list
        for index, layer in enumerate(self.iface.legendInterface().layers()):
            if layer.type() == QgsMapLayer.VectorLayer:
                # if there are selected features toggle has_selected_features
                if layer.selectedFeatureCount():
                    has_selected_features = True
                self.dlg.ls_layers.addItem(layer.name())
                # select the active layer by default
                if layer.name() == active_layer_name:
                    self.dlg.ls_layers.setCurrentRow(index)

        # if at least one vector layer has selected features enable checkbutton cb_selected_only
        if has_selected_features:
            self.dlg.cb_selected_only.setEnabled(True)
            self.dlg.cb_selected_only.setChecked(True)
        else:
            self.dlg.cb_selected_only.setChecked(False)
            self.dlg.cb_selected_only.setEnabled(False)

        # initialize cb_output
        # remember the layer being selected the last time
        last_index = self.dlg.cb_output.currentText()
        # populate the combo box with the polygon layers listed in the current legend
        self.set_output_layer_combobox(2, last_index)

        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()

        # See if OK was pressed
        if result == 1:
            geom = []
            # read selected list entries and get the map layer
            for layer_name in self.dlg.ls_layers.selectedItems():
                active_layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name.text())[0]
                # get all or the currently selected features according to state of cb_selected_only
                # convert each feature to points
                if active_layer.selectedFeatureCount() and self.dlg.cb_selected_only.checkState():
                    for feat in active_layer.selectedFeatures():
                        geom.extend(extract_points(feat.geometry()))
                else:
                    for feat in active_layer.getFeatures():
                        geom.extend(extract_points(feat.geometry()))

            num_points = len(geom)
            if num_points == 0:
                return None

            # Send WARNING to the message bar to inform about a probably long running time
            if num_points > 1000:
                msg = self.msg_bar.createMessage(u'Please be patient, processing of more then {} points may take a while'.
                                                 format(int(num_points)))
                self.msg_bar.pushWidget(msg, QgsMessageBar.WARNING, 2)

            # if more then 5000 points ask user to confirm
            if num_points > 5000:
                proceed = QMessageBox.question(None, 'Please confirm', 'Do you really want to proceed?',
                                             QMessageBox.Yes | QMessageBox.No)
                if proceed == QMessageBox.No:
                    QApplication.instance().setOverrideCursor(Qt.ArrowCursor)
                    return None

            # change cursor to inform user about ongoing processing
            QApplication.instance().setOverrideCursor(Qt.BusyCursor)

            # generate the hull geometry
            # process points with prior clustering
            hull_list = []
            if self.dlg.gb_clustering.isChecked():
                clusters = SSNClusters(geom, self.dlg.sb_neighborhood_list_size.value()).get_clusters()
                for cluster in clusters.keys():
                    the_hull = concave_hull(clusters[cluster], self.dlg.sb_neighbors.value())
                    if the_hull:
                        hull_list.append([as_polygon(the_hull), len(clusters[cluster])])
            else:
                # process points without clustering
                the_hull = concave_hull(geom, self.dlg.sb_neighbors.value())
                hull_list.append([as_polygon(the_hull), len(geom)])

            # write hull geometries to output device
            success = self.create_output_feature(hull_list)

            # report result in QGIS message bar
            if success:
                msg = self.msg_bar.createMessage(_translate('ConcaveHull', '{} Concave hulls created successfully'.
                                                            format(int(len(hull_list))), None))
                self.msg_bar.pushWidget(msg, QgsMessageBar.INFO, 5)

            # reset cursor
            QApplication.instance().setOverrideCursor(Qt.ArrowCursor)

        return None
Beispiel #4
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        SELECTED_ONLY = self.getParameterValue(self.SELECTED_ONLY)
        kneighbors = int(self.getParameterValue(self.KNEIGHBORS))
        use_field = self.getParameterValue(self.METHOD) == 1
        field_name = self.getParameterValue(self.FIELD)

        # temporarily alter the processing environment
        old_setting = ProcessingConfig.getSetting(
            ProcessingConfig.USE_SELECTED)
        ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED,
                                         SELECTED_ONLY)

        # get properties of the field the grouping is based on
        if use_field:
            field = QgsField(field_name)
            field.setType(QVariant.String)
            field.setLength(255)
            index = layer.fieldNameIndex(field_name)
            field_type = layer.pendingFields()[index].type()
            if field_type == QVariant.Int:
                field.setType(QVariant.Int)
                field.setLength(20)
            elif field_type == QVariant.Double:
                field.setType(QVariant.Double)
                field.setLength(20)
                field.setPrecision(6)
            else:
                field.setType(QVariant.String)
                field.setLength(255)
            fields = [QgsField('clusterId', QVariant.Int, '', 20), field]
        else:
            # setup the fields of the output layer
            fields = [QgsField('clusterId', QVariant.Int, '', 20)]
            #fields.extend(layer.pendingFields().toList())

        # initialize writer
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPoint, layer.crs())

        current = 0
        fid = 1

        if use_field:
            # get unique values of field denoted by index as filter conditions
            unique_values = layer.uniqueValues(index)
            total = 100.0 / float(layer.featureCount() * len(unique_values))

            for unique in unique_values:
                points = []
                first = True
                features = vector.features(layer)
                for in_feature in features:
                    value = in_feature[field_name]
                    if value == unique:
                        if first:
                            val = unique
                            first = False
                        points.extend(
                            vector.extractPoints(
                                QgsGeometry(in_feature.geometry())))
                    current += 1
                    progress.setPercentage(int(current * total))

                # A minimum of 3 points is necessary to proceed
                if len(points) >= 3:
                    out_feature = QgsFeature()
                    try:
                        clusters = SSNClusters(points,
                                               kneighbors).get_clusters()
                        for cluster in clusters.keys():
                            #mpoint = QgsGeometry.fromMultiPoint([QgsPoint(point[0], point[1]) for point in clusters[cluster]])
                            for member in clusters[cluster]:
                                point = QgsGeometry.fromPoint(
                                    QgsPoint(member[0], member[1]))

                                out_feature.setGeometry(point)
                                out_feature.setAttributes([fid, val])
                                writer.addFeature(out_feature)
                            fid += 1
                    except:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            'Exception while computing clusters.')
                        raise GeoAlgorithmExecutionException(
                            'Exception while computing clusters.')
                    finally:
                        ProcessingConfig.setSettingValue(
                            ProcessingConfig.USE_SELECTED, old_setting)

        else:
            points = []
            features = vector.features(layer)
            total = 100.0 / float(len(features))
            for in_feature in features:
                ##points.append(in_feature.geometry().asPoint())
                points.extend(
                    vector.extractPoints(QgsGeometry(in_feature.geometry())))
                current += 1
                progress.setPercentage(int(current * total))

            out_feature = QgsFeature()
            try:
                clusters = SSNClusters(points, kneighbors).get_clusters()
                for cluster in clusters.keys():
                    #mpoint = QgsGeometry.fromMultiPoint([QgsPoint(point[0], point[1]) for point in clusters[cluster]])
                    for member in clusters[cluster]:
                        point = QgsGeometry.fromPoint(
                            QgsPoint(member[0], member[1]))

                        out_feature.setGeometry(point)
                        out_feature.setAttributes([cluster])
                        writer.addFeature(out_feature)
            except:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                       'Exception while computing clusters.')
                raise GeoAlgorithmExecutionException(
                    'Exception while computing clusters')
            finally:
                ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED,
                                                 old_setting)

        del writer