Exemple #1
0
    def processAlgorithm(self, feedback):
        inLayer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY
        smallestArea = self.getParameterValue(
            self.MODE) == self.MODE_SMALLEST_AREA
        keepSelection = self.getParameterValue(self.KEEPSELECTION)
        processLayer = vector.duplicateInMemory(inLayer)

        if not keepSelection:
            # Make a selection with the values provided
            attribute = self.getParameterValue(self.ATTRIBUTE)
            comparison = self.comparisons[self.getParameterValue(
                self.COMPARISON)]
            comparisonvalue = self.getParameterValue(self.COMPARISONVALUE)

            selectindex = vector.resolveFieldIndex(processLayer, attribute)
            selectType = processLayer.fields()[selectindex].type()
            selectionError = False

            if selectType in [
                    QVariant.Int, QVariant.LongLong, QVariant.UInt,
                    QVariant.ULongLong
            ]:
                try:
                    y = int(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to integer' %
                                  str(comparisonvalue))
            elif selectType == QVariant.Double:
                try:
                    y = float(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to float' %
                                  str(comparisonvalue))
            elif selectType == QVariant.String:
                # 10: string, boolean
                try:
                    y = str(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to Unicode' %
                                  str(comparisonvalue))
            elif selectType == QVariant.Date:
                # date
                dateAndFormat = comparisonvalue.split(' ')

                if len(dateAndFormat) == 1:
                    # QDate object
                    y = QLocale.system().toDate(dateAndFormat[0])

                    if y.isNull():
                        msg = self.tr(
                            'Cannot convert "%s" to date with system date format %s'
                            % (str(dateAndFormat),
                               QLocale.system().dateFormat()))
                elif len(dateAndFormat) == 2:
                    y = QDate.fromString(dateAndFormat[0], dateAndFormat[1])

                    if y.isNull():
                        msg = self.tr(
                            'Cannot convert "%s" to date with format string "%s"'
                            % (str(dateAndFormat[0]), dateAndFormat[1]))
                else:
                    y = QDate()
                    msg = ''

                if y.isNull():
                    # Conversion was unsuccessful
                    selectionError = True
                    msg += self.tr(
                        'Enter the date and the date format, e.g. "07.26.2011" "MM.dd.yyyy".'
                    )

            if (comparison == 'begins with' or comparison == 'contains') \
               and selectType != QVariant.String:
                selectionError = True
                msg = self.tr('"%s" can only be used with string fields' %
                              comparison)

            selected = []

            if selectionError:
                raise GeoAlgorithmExecutionException(
                    self.tr('Error in selection input: %s' % msg))
            else:
                for feature in processLayer.getFeatures():
                    aValue = feature.attributes()[selectindex]

                    if aValue is None:
                        continue

                    if selectType in [
                            QVariant.Int, QVariant.LongLong, QVariant.UInt,
                            QVariant.ULongLong
                    ]:
                        x = int(aValue)
                    elif selectType == QVariant.Double:
                        x = float(aValue)
                    elif selectType == QVariant.String:
                        # 10: string, boolean
                        x = str(aValue)
                    elif selectType == QVariant.Date:
                        # date
                        x = aValue  # should be date

                    match = False

                    if comparison == '==':
                        match = x == y
                    elif comparison == '!=':
                        match = x != y
                    elif comparison == '>':
                        match = x > y
                    elif comparison == '>=':
                        match = x >= y
                    elif comparison == '<':
                        match = x < y
                    elif comparison == '<=':
                        match = x <= y
                    elif comparison == 'begins with':
                        match = x.startswith(y)
                    elif comparison == 'contains':
                        match = x.find(y) >= 0

                    if match:
                        selected.append(feature.id())

            processLayer.selectByIds(selected)

        if processLayer.selectedFeatureCount() == 0:
            ProcessingLog.addToLog(
                ProcessingLog.LOG_WARNING,
                self.tr('%s: (No selection in input layer "%s")' %
                        (self.commandLineName(),
                         self.getParameterValue(self.INPUT))))

        # Keep references to the features to eliminate
        featToEliminate = []
        for aFeat in processLayer.selectedFeatures():
            featToEliminate.append(aFeat)

        # Delete all features to eliminate in processLayer (we won't save this)
        processLayer.startEditing()
        processLayer.deleteSelectedFeatures()

        # ANALYZE
        if len(featToEliminate) > 0:  # Prevent zero division
            start = 20.00
            add = 80.00 / len(featToEliminate)
        else:
            start = 100

        feedback.setProgress(start)
        madeProgress = True

        # We go through the list and see if we find any polygons we can
        # merge the selected with. If we have no success with some we
        # merge and then restart the whole story.
        while madeProgress:  # Check if we made any progress
            madeProgress = False
            featNotEliminated = []

            # Iterate over the polygons to eliminate
            for i in range(len(featToEliminate)):
                feat = featToEliminate.pop()
                geom2Eliminate = feat.geometry()
                bbox = geom2Eliminate.boundingBox()
                fit = processLayer.getFeatures(
                    QgsFeatureRequest().setFilterRect(
                        bbox).setSubsetOfAttributes([]))
                mergeWithFid = None
                mergeWithGeom = None
                max = 0
                min = -1
                selFeat = QgsFeature()

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(
                    geom2Eliminate.geometry())
                engine.prepareGeometry()

                while fit.nextFeature(selFeat):
                    selGeom = selFeat.geometry()

                    if engine.intersects(selGeom.geometry()):
                        # We have a candidate
                        iGeom = geom2Eliminate.intersection(selGeom)

                        if not iGeom:
                            continue

                        if boundary:
                            selValue = iGeom.length()
                        else:
                            # area. We need a common boundary in
                            # order to merge
                            if 0 < iGeom.length():
                                selValue = selGeom.area()
                            else:
                                selValue = -1

                        if -1 != selValue:
                            useThis = True

                            if smallestArea:
                                if -1 == min:
                                    min = selValue
                                else:
                                    if selValue < min:
                                        min = selValue
                                    else:
                                        useThis = False
                            else:
                                if selValue > max:
                                    max = selValue
                                else:
                                    useThis = False

                            if useThis:
                                mergeWithFid = selFeat.id()
                                mergeWithGeom = QgsGeometry(selGeom)
                # End while fit

                if mergeWithFid is not None:
                    # A successful candidate
                    newGeom = mergeWithGeom.combine(geom2Eliminate)

                    if processLayer.changeGeometry(mergeWithFid, newGeom):
                        madeProgress = True
                    else:
                        raise GeoAlgorithmExecutionException(
                            self.
                            tr('Could not replace geometry of feature with id %s'
                               % mergeWithFid))

                    start = start + add
                    feedback.setProgress(start)
                else:
                    featNotEliminated.append(feat)

            # End for featToEliminate

            featToEliminate = featNotEliminated

        # End while

        # Create output
        output = self.getOutputFromName(self.OUTPUT)
        writer = output.getVectorWriter(processLayer.fields(),
                                        processLayer.wkbType(),
                                        processLayer.crs())

        # Write all features that are left over to output layer
        iterator = processLayer.getFeatures()
        for feature in iterator:
            writer.addFeature(feature)

        # Leave processLayer untouched
        processLayer.rollBack()

        for feature in featNotEliminated:
            writer.addFeature(feature)
Exemple #2
0
    def processAlgorithm(self, feedback):
        inLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY
        smallestArea = self.getParameterValue(self.MODE) == self.MODE_SMALLEST_AREA
        keepSelection = self.getParameterValue(self.KEEPSELECTION)
        processLayer = vector.duplicateInMemory(inLayer)

        if not keepSelection:
            # Make a selection with the values provided
            attribute = self.getParameterValue(self.ATTRIBUTE)
            comparison = self.comparisons[self.getParameterValue(self.COMPARISON)]
            comparisonvalue = self.getParameterValue(self.COMPARISONVALUE)

            selectindex = vector.resolveFieldIndex(processLayer, attribute)
            selectType = processLayer.fields()[selectindex].type()
            selectionError = False

            if selectType in [QVariant.Int, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
                try:
                    y = int(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to integer' % str(comparisonvalue))
            elif selectType == QVariant.Double:
                try:
                    y = float(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to float' % str(comparisonvalue))
            elif selectType == QVariant.String:
                # 10: string, boolean
                try:
                    y = str(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to Unicode' % str(comparisonvalue))
            elif selectType == QVariant.Date:
                # date
                dateAndFormat = comparisonvalue.split(' ')

                if len(dateAndFormat) == 1:
                    # QDate object
                    y = QLocale.system().toDate(dateAndFormat[0])

                    if y.isNull():
                        msg = self.tr('Cannot convert "%s" to date with system date format %s' % (str(dateAndFormat), QLocale.system().dateFormat()))
                elif len(dateAndFormat) == 2:
                    y = QDate.fromString(dateAndFormat[0], dateAndFormat[1])

                    if y.isNull():
                        msg = self.tr('Cannot convert "%s" to date with format string "%s"' % (str(dateAndFormat[0]), dateAndFormat[1]))
                else:
                    y = QDate()
                    msg = ''

                if y.isNull():
                    # Conversion was unsuccessful
                    selectionError = True
                    msg += self.tr('Enter the date and the date format, e.g. "07.26.2011" "MM.dd.yyyy".')

            if (comparison == 'begins with' or comparison == 'contains') \
               and selectType != QVariant.String:
                selectionError = True
                msg = self.tr('"%s" can only be used with string fields' % comparison)

            selected = []

            if selectionError:
                raise GeoAlgorithmExecutionException(
                    self.tr('Error in selection input: %s' % msg))
            else:
                for feature in processLayer.getFeatures():
                    aValue = feature.attributes()[selectindex]

                    if aValue is None:
                        continue

                    if selectType in [QVariant.Int, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
                        x = int(aValue)
                    elif selectType == QVariant.Double:
                        x = float(aValue)
                    elif selectType == QVariant.String:
                        # 10: string, boolean
                        x = str(aValue)
                    elif selectType == QVariant.Date:
                        # date
                        x = aValue  # should be date

                    match = False

                    if comparison == '==':
                        match = x == y
                    elif comparison == '!=':
                        match = x != y
                    elif comparison == '>':
                        match = x > y
                    elif comparison == '>=':
                        match = x >= y
                    elif comparison == '<':
                        match = x < y
                    elif comparison == '<=':
                        match = x <= y
                    elif comparison == 'begins with':
                        match = x.startswith(y)
                    elif comparison == 'contains':
                        match = x.find(y) >= 0

                    if match:
                        selected.append(feature.id())

            processLayer.selectByIds(selected)

        if processLayer.selectedFeatureCount() == 0:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                   self.tr('%s: (No selection in input layer "%s")' % (self.commandLineName(), self.getParameterValue(self.INPUT))))

        # Keep references to the features to eliminate
        featToEliminate = []
        for aFeat in processLayer.selectedFeatures():
            featToEliminate.append(aFeat)

        # Delete all features to eliminate in processLayer (we won't save this)
        processLayer.startEditing()
        processLayer.deleteSelectedFeatures()

        # ANALYZE
        if len(featToEliminate) > 0:  # Prevent zero division
            start = 20.00
            add = 80.00 / len(featToEliminate)
        else:
            start = 100

        feedback.setProgress(start)
        madeProgress = True

        # We go through the list and see if we find any polygons we can
        # merge the selected with. If we have no success with some we
        # merge and then restart the whole story.
        while madeProgress:  # Check if we made any progress
            madeProgress = False
            featNotEliminated = []

            # Iterate over the polygons to eliminate
            for i in range(len(featToEliminate)):
                feat = featToEliminate.pop()
                geom2Eliminate = feat.geometry()
                bbox = geom2Eliminate.boundingBox()
                fit = processLayer.getFeatures(
                    QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes([]))
                mergeWithFid = None
                mergeWithGeom = None
                max = 0
                min = -1
                selFeat = QgsFeature()

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom2Eliminate.geometry())
                engine.prepareGeometry()

                while fit.nextFeature(selFeat):
                    selGeom = selFeat.geometry()

                    if engine.intersects(selGeom.geometry()):
                        # We have a candidate
                        iGeom = geom2Eliminate.intersection(selGeom)

                        if not iGeom:
                            continue

                        if boundary:
                            selValue = iGeom.length()
                        else:
                            # area. We need a common boundary in
                            # order to merge
                            if 0 < iGeom.length():
                                selValue = selGeom.area()
                            else:
                                selValue = -1

                        if -1 != selValue:
                            useThis = True

                            if smallestArea:
                                if -1 == min:
                                    min = selValue
                                else:
                                    if selValue < min:
                                        min = selValue
                                    else:
                                        useThis = False
                            else:
                                if selValue > max:
                                    max = selValue
                                else:
                                    useThis = False

                            if useThis:
                                mergeWithFid = selFeat.id()
                                mergeWithGeom = QgsGeometry(selGeom)
                # End while fit

                if mergeWithFid is not None:
                    # A successful candidate
                    newGeom = mergeWithGeom.combine(geom2Eliminate)

                    if processLayer.changeGeometry(mergeWithFid, newGeom):
                        madeProgress = True
                    else:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Could not replace geometry of feature with id %s' % mergeWithFid))

                    start = start + add
                    feedback.setProgress(start)
                else:
                    featNotEliminated.append(feat)

            # End for featToEliminate

            featToEliminate = featNotEliminated

        # End while

        # Create output
        output = self.getOutputFromName(self.OUTPUT)
        writer = output.getVectorWriter(processLayer.fields(),
                                        processLayer.wkbType(), processLayer.crs())

        # Write all features that are left over to output layer
        iterator = processLayer.getFeatures()
        for feature in iterator:
            writer.addFeature(feature)

        # Leave processLayer untouched
        processLayer.rollBack()

        for feature in featNotEliminated:
            writer.addFeature(feature)