Ejemplo n.º 1
0
    def bbToMap(self, fullWkt=False):
        '''takes bounding box coords and puts them on the map'''
        #if self.foi_type == "AreaOfInterestDefiner":
        if not fullWkt:
            ix = self.bbMinXText.text()
            iy = self.bbMinYText.text()
            ax = self.bbMaxXText.text()
            ay = self.bbMaxYText.text()

            wkt = "POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))" % \
                  (ix,  iy,  ix,  ay,  ax,  ay,  ax,  iy,  ix,  iy)
        else:
            wkt = self.asTxtText.toPlainText()
        try:
            errnum = 0
            geom = QgsGeometry().fromWkt(wkt)
            print "gotGeom"
            if self.foi_type == "AreaOfInterestDefiner" and geom.type() != 2:
                errnum = 1
            elif self.foi_type == "LineOfInterestDefiner" and geom.type() != 1:
                errnum = 1
            elif self.foi_type == "PointOfInterestDefiner" and geom.type() != 0:
                errnum = 1
            else:
                print "attempting to add geometry to mem layer"
                self.addGeomToMemoryLayer(geom)

            if errnum == 1:
                raise ModuleError(self, "Incorrect Geometry Type chosen")
        except:
            raise ModuleError(self, "Could not generate Geometry from text provided")
Ejemplo n.º 2
0
def qGeometry(feature):
    try:
        geom = QgsGeometry(feature.geometry())
        fid = feature.id()
        if not geom.isMultipart():
            if not geom.convertToMultiType():
                raise Exception("unable to extract feature geometry (invalid geometry type)")
        if geom.type() == 0:
            return qPoints(geom.asMultiPoint())
        elif geom.type() == 1:
            return qLines(geom.asMultiPolyline(), fid)
        elif geom.type() == 2:
            return qPolygons(geom.asMultiPolygon(), fid)
        else:
            raise Exception("unable to extract feature geometry (unknown geometry type)")
    except Exception, e:
        raise Exception("unable to extract feature geometry: %s" % unicode(e))
Ejemplo n.º 3
0
 def checkGeom(self, expected_type):
     '''Check the geom to see if it can be instantiated as the expected type
         - enum of {'point','line','polygon'}'''
     testGeom = QgsGeometry().fromWkt(self.wkt)
     if expected_type == 'point':
         if testGeom.type() == 0:
             return True
         else:
             return False
     if expected_type == 'line':
         if testGeom.type() == 1:
             return True
         else:
             return False
     if expected_type == 'polygon':
         if testGeom.type() == 2:
             return True
         else:
             return False
Ejemplo n.º 4
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        fieldName = self.getParameterValue(self.FIELD)

        geomType = self.singleToMultiGeom(layer.wkbType())

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.fields().toList(), geomType, layer.crs())

        inFeat = QgsFeature()
        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        index = layer.fields().lookupField(fieldName)
        unique = vector.getUniqueValues(layer, index)

        current = 0
        features = vector.features(layer)
        total = 100.0 / (len(features) * len(unique))
        if not len(unique) == layer.featureCount():
            for i in unique:
                multi_feature = []
                first = True
                features = vector.features(layer)
                for inFeat in features:
                    atMap = inFeat.attributes()
                    idVar = atMap[index]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            attrs = atMap
                            first = False
                        inGeom = inFeat.geometry()
                        vType = inGeom.type()
                        feature_list = self.extractAsMulti(inGeom)
                        multi_feature.extend(feature_list)

                    current += 1
                    progress.setPercentage(int(current * total))

                outFeat.setAttributes(attrs)
                outGeom = QgsGeometry(
                    self.convertGeometry(multi_feature, vType))
                outFeat.setGeometry(outGeom)
                writer.addFeature(outFeat)

            del writer
        else:
            raise GeoAlgorithmExecutionException(
                self.tr('At least two features must have same attribute '
                        'value! Please choose another field...'))
Ejemplo n.º 5
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        fieldName = self.getParameterValue(self.FIELD)

        geomType = self.singleToMultiGeom(layer.wkbType())

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.fields().toList(), geomType, layer.crs())

        inFeat = QgsFeature()
        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        index = layer.fields().lookupField(fieldName)
        unique = vector.getUniqueValues(layer, index)

        current = 0
        features = vector.features(layer)
        total = 100.0 / (len(features) * len(unique))
        if not len(unique) == layer.featureCount():
            for i in unique:
                multi_feature = []
                first = True
                features = vector.features(layer)
                for inFeat in features:
                    atMap = inFeat.attributes()
                    idVar = atMap[index]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            attrs = atMap
                            first = False
                        inGeom = inFeat.geometry()
                        vType = inGeom.type()
                        feature_list = self.extractAsMulti(inGeom)
                        multi_feature.extend(feature_list)

                    current += 1
                    progress.setPercentage(int(current * total))

                outFeat.setAttributes(attrs)
                outGeom = QgsGeometry(self.convertGeometry(multi_feature,
                                                           vType))
                outFeat.setGeometry(outGeom)
                writer.addFeature(outFeat)

            del writer
        else:
            raise GeoAlgorithmExecutionException(
                self.tr('At least two features must have same attribute '
                        'value! Please choose another field...'))
Ejemplo n.º 6
0
    def highlight(self, geometry: QgsGeometry):
        self.rubber_band.reset(geometry.type())
        self.rubber_band.addGeometry(geometry, None)

        rect = geometry.boundingBox()
        if not self.settings.value('keep_scale'):
            if rect.isEmpty():
                current_extent = self.map_canvas.extent()
                rect = current_extent.scaled(self.settings.value(
                    'point_scale')/self.map_canvas.scale(), rect.center())
            else:
                rect.scale(4)
        self.map_canvas.setExtent(rect)
        self.map_canvas.refresh()
Ejemplo n.º 7
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        fieldName = self.getParameterValue(self.FIELD)

        geomType = QgsWkbTypes.multiType(layer.wkbType())

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.fields().toList(), geomType, layer.crs())

        inFeat = QgsFeature()
        outFeat = QgsFeature()
        inGeom = QgsGeometry()

        index = layer.fields().lookupField(fieldName)

        collection_geom = {}
        collection_attrs = {}

        features = vector.features(layer)
        current = 0
        total = 100.0 / (len(features))

        features = vector.features(layer)
        for inFeat in features:
            atMap = inFeat.attributes()
            idVar = atMap[index]
            key = str(idVar).strip()
            if not key in collection_geom:
                collection_geom[key] = []
                collection_attrs[key] = atMap

            inGeom = inFeat.geometry()
            vType = inGeom.type()
            collection_geom[key].append(inGeom)

            current += 1
            progress.setPercentage(int(current * total))

        for key, geoms in collection_geom.items():
            outFeat.setAttributes(collection_attrs[key])
            outFeat.setGeometry(QgsGeometry.collectGeometry(geoms))
            writer.addFeature(outFeat)

        del writer
Ejemplo n.º 8
0
    def zoom(self, error, crs):
        if not error: return
        geo = error.geo
        mapSettings = self.mapCanvas.mapSettings()
        if isProjectCrsEnabled() and getProjectCrs() != crs:
            geo = QgsGeometry(error.geo)
            transform = QgsCoordinateTransform(crs, QgsProject().instance().crs())
            geo.transform(transform)

        if geo.type() == QgsWkbTypes.PointGeometry:
            p = geo.asPoint()
            bufferCrs = getProjectCrs() if isProjectCrsEnabled() else crs
            b = 2000 if not bufferCrs.isGeographic() else 2000 / 100000  # buffer
            extent = QgsRectangle(p.x() - b, p.y() - b, p.x() + b, p.y() + b)
        else:  # line
            extent = geo.boundingBox()
            extent.scale(2)
        self.mapCanvas.setExtent(extent)
        self.mapCanvas.refresh();
Ejemplo n.º 9
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        spatialRealtionsHandler = SpatialRelationsHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        heightFieldName = self.parameterAsFields(parameters, self.CONTOUR_ATTR,
                                                 context)[0]
        threshold = self.parameterAsDouble(parameters, self.CONTOUR_INTERVAL,
                                           context)
        geoBoundsLyr = self.parameterAsVectorLayer(parameters,
                                                   self.GEOGRAPHIC_BOUNDS,
                                                   context)
        point_flagSink, point_flag_id = self.prepareAndReturnFlagSink(
            parameters, inputLyr, QgsWkbTypes.Point, context, self.POINT_FLAGS)
        line_flagSink, line_flag_id = self.prepareAndReturnFlagSink(
            parameters, inputLyr, QgsWkbTypes.LineString, context,
            self.LINE_FLAGS)

        invalidDict = spatialRealtionsHandler.validateTerrainModel(
            contourLyr=inputLyr,
            onlySelected=onlySelected,
            heightFieldName=heightFieldName,
            threshold=threshold,
            geoBoundsLyr=geoBoundsLyr,
            feedback=feedback)

        for flagGeom, text in invalidDict.items():
            geom = QgsGeometry()
            geom.fromWkb(flagGeom)
            flagSink = line_flagSink if geom.type(
            ) == QgsWkbTypes.LineGeometry else point_flagSink
            self.flagFeature(geom, text, fromWkb=False, sink=flagSink)

        return {self.POINT_FLAGS: point_flag_id, self.LINE_FLAGS: line_flag_id}
Ejemplo n.º 10
0
    def highlight(self, geometry: QgsGeometry):
        self.clearPreviousResults()
        if geometry is None:
            return

        self.rubber_band.reset(geometry.type())
        self.rubber_band.addGeometry(geometry, None)

        rect = geometry.boundingBox()
        if not self.settings.value('keep_scale'):
            if rect.isEmpty():
                current_extent = self.map_canvas.extent()
                rect = current_extent.scaled(
                    self.settings.value('point_scale') /
                    self.map_canvas.scale(), rect.center())
            else:
                rect.scale(4)
        self.map_canvas.setExtent(rect)
        self.map_canvas.refresh()

        self.current_timer = QTimer()
        self.current_timer.timeout.connect(self.clearPreviousResults)
        self.current_timer.setSingleShot(True)
        self.current_timer.start(5000)
Ejemplo n.º 11
0
def get_features(layername, ftype=None, selected=False):
    """ Create a list of selected or all features
        from a given layer possibly with given type.

        :param layername: name of the layer
        :param ftype: type of features to add to the list (if None - all features)
        :param selected: if True only selected features will be added to the list
        :returns: list of feature geometries (QgsGeometry list)
    """
    w = []
    lay = get_layer_by_name(layername)
    if lay is None:
        return None
    if selected:
        features = lay.selectedFeatures()
    else:
        features = lay.getFeatures()
    for feat in features:
        geom = QgsGeometry(feat.geometry())
        if type is None or geom.type() == ftype:
            w.append(geom)
    if len(w):
        return w
    return None
Ejemplo n.º 12
0
    def compute(self, inName, joinName, outName, summary, sumList, keep,
                progressBar):
        layer1 = ftools_utils.getVectorLayerByName(inName)
        provider1 = layer1.dataProvider()
        fieldList1 = ftools_utils.getFieldList(layer1)

        layer2 = ftools_utils.getVectorLayerByName(joinName)
        provider2 = layer2.dataProvider()

        fieldList2 = ftools_utils.getFieldList(layer2)
        fieldList = QgsFields()
        if provider1.crs() != provider2.crs():
            QMessageBox.warning(
                self, self.tr("CRS warning!"),
                self.
                tr("Warning: Input layers have non-matching CRS.\nThis may cause unexpected results."
                   ))
        if not summary:
            fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList2)
            seq = range(0, len(fieldList1) + len(fieldList2))
            fieldList1.extend(fieldList2)
            fieldList1 = dict(zip(seq, fieldList1))
        else:
            numFields = {}
            for j in xrange(len(fieldList2)):
                if fieldList2[j].type() == QVariant.Int or fieldList2[j].type(
                ) == QVariant.Double:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + unicode(fieldList2[j].name()),
                                         QVariant.Double, "real", 24, 16,
                                         self.tr("Summary field"))
                        fieldList.append(field)
            field = QgsField("COUNT", QVariant.Double, "real", 24, 16,
                             self.tr("Summary field"))
            fieldList.append(field)
            fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList)
            fieldList1.extend(fieldList)
            seq = range(0, len(fieldList1))
            fieldList1 = dict(zip(seq, fieldList1))

        sRs = provider1.crs()
        progressBar.setValue(13)
        check = QFile(self.shapefileName)
        if check.exists():
            if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName):
                QMessageBox.warning(
                    self, self.tr('Error deleting shapefile'),
                    self.tr("Can't delete existing shapefile\n%s") %
                    (self.shapefileName))
                return False
        fields = QgsFields()
        for f in fieldList1.values():
            fields.append(f)
        writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields,
                                     provider1.geometryType(), sRs)
        #writer = QgsVectorFileWriter(outName, "UTF-8", fieldList1, provider1.geometryType(), sRs)
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()
        progressBar.setValue(15)
        start = 15.00
        add = 85.00 / provider1.featureCount()

        index = ftools_utils.createIndex(provider2)

        # cache all features from provider2 to avoid huge number of feature requests in the inner loop
        mapP2 = {}
        for f in provider2.getFeatures():
            mapP2[f.id()] = QgsFeature(f)

        fit1 = provider1.getFeatures()
        while fit1.nextFeature(inFeat):
            inGeom = inFeat.geometry()
            atMap1 = inFeat.attributes()
            outFeat.setGeometry(inGeom)
            none = True
            joinList = []
            if inGeom.type() == QGis.Point:
                #(check, joinList) = layer2.featuresInRectangle(inGeom.buffer(10,2).boundingBox(), True, True)
                #layer2.select(inGeom.buffer(10,2).boundingBox(), False)
                #joinList = layer2.selectedFeatures()
                joinList = index.intersects(inGeom.buffer(10, 2).boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            else:
                #(check, joinList) = layer2.featuresInRectangle(inGeom.boundingBox(), True, True)
                #layer2.select(inGeom.boundingBox(), False)
                #joinList = layer2.selectedFeatures()
                joinList = index.intersects(inGeom.boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            if check == 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]  # cached feature from provider2
                    if inGeom.intersects(inFeatB.geometry()):
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])
                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == "SUM":
                                atMap.append(sum(filter_null(numFields[j])))
                            elif k == "MEAN":
                                try:
                                    nn_count = sum(
                                        1 for _ in filter_null(numFields[j]))
                                    atMap.append(
                                        sum(filter_null(numFields[j])) /
                                        nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == "MIN":
                                try:
                                    atMap.append(min(filter_null(
                                        numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == "MED":
                                atMap.append(myself(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(filter_null(
                                        numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())
            if keep:  # keep all records
                writer.addFeature(outFeat)
            else:  # keep only matching records
                if not none:
                    writer.addFeature(outFeat)
            start = start + add
            progressBar.setValue(start)
        del writer
        return True
Ejemplo n.º 13
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))
        GEOS_EXCEPT = True
        FEATURE_EXCEPT = True
        vproviderA = vlayerA.dataProvider()

        fields = vector.combineVectorFields(vlayerA, vlayerB)
        names = [field.name() for field in fields]
        ProcessingLog.addToLog(ProcessingLog.LOG_INFO, str(names))
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(
            fields, vproviderA.geometryType(), vproviderA.crs()
        )
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            found = False
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union"))
            else:
                for id in intersects:
                    count += 1
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerB.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if geom.intersects(tmpGeom):
                        found = True
                        int_geom = geom.intersection(tmpGeom)

                        if int_geom is None:
                            # There was a problem creating the intersection
                            raise GeoAlgorithmExecutionException(
                                self.tr("Geometry exception while computing " "intersection")
                            )
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if diff_geom.intersects(tmpGeom):
                            diff_geom = diff_geom.difference(tmpGeom)
                            if diff_geom is None:
                                # It's possible there was an error here?
                                diff_geom = QgsGeometry()
                            else:
                                diff_geom = QgsGeometry(diff_geom)

                        if int_geom.wkbType() == 0:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                        try:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                        except Exception, err:
                            raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union"))
                    else:
                        # This only happends if the bounding box intersects,
                        # but the geometry doesn't
                        try:
                            outFeat.setGeometry(geom)
                            outFeat.setAttributes(atMapA)
                            writer.addFeature(outFeat)
                        except:
                            # Also shoudn't ever happen
                            raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union"))

                if found:
                    try:
                        if diff_geom.wkbType() == 0:
                            temp_list = diff_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    diff_geom = QgsGeometry(i)
                        outFeat.setGeometry(diff_geom)
                        outFeat.setAttributes(atMapA)
                        writer.addFeature(outFeat)
                    except Exception, err:
                        raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union"))
Ejemplo n.º 14
0
    def processAlgorithm(self, parameters, context, feedback):
        if DEBUG_MODE:
            logMessage(
                "processAlgorithm(): {}".format(self.__class__.__name__),
                False)

        clayer = self.parameterAsLayer(parameters, self.INPUT, context)
        title_field = self.parameterAsString(parameters, self.TITLE_FIELD,
                                             context)
        cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context)
        fixed_scale = self.parameterAsEnum(parameters, self.SCALE,
                                           context)  # == 1
        buf = self.parameterAsDouble(parameters, self.BUFFER, context)
        tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context)
        orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT,
                                              context)

        header_exp = QgsExpression(
            self.parameterAsExpression(parameters, self.HEADER, context))
        footer_exp = QgsExpression(
            self.parameterAsExpression(parameters, self.FOOTER, context))

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(clayer))

        out_dir = self.parameterAsString(parameters, self.OUTPUT, context)
        if not QDir(out_dir).exists():
            QDir().mkpath(out_dir)

        if DEBUG_MODE:
            openDirectory(out_dir)

        mapSettings = self.controller.settings.mapSettings
        baseExtent = self.controller.settings.baseExtent
        rotation = mapSettings.rotation()
        orig_size = mapSettings.outputSize()

        if cf_filter:
            cf_layer = QgsMemoryProviderUtils.createMemoryLayer(
                "current feature", clayer.fields(), clayer.wkbType(),
                clayer.crs())
            layers = [
                cf_layer if lyr == clayer else lyr
                for lyr in mapSettings.layers()
            ]
            mapSettings.setLayers(layers)

            doc = QDomDocument("qgis")
            clayer.exportNamedStyle(doc)
            cf_layer.importNamedStyle(doc)

        total = clayer.featureCount()
        for current, feature in enumerate(clayer.getFeatures()):
            if feedback.isCanceled():
                break

            if cf_filter:
                cf_layer.startEditing()
                cf_layer.deleteFeatures(
                    [f.id() for f in cf_layer.getFeatures()])
                cf_layer.addFeature(feature)
                cf_layer.commitChanges()

            title = feature.attribute(title_field)
            feedback.setProgressText("({}/{}) Exporting {}...".format(
                current + 1, total, title))
            logMessage("Exporting {}...".format(title), False)

            # extent
            geometry = QgsGeometry(feature.geometry())
            geometry.transform(self.transform)
            center = geometry.centroid().asPoint()

            if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry:
                tex_height = orig_tex_height or int(
                    tex_width * orig_size.height() / orig_size.width())
                rect = RotatedRect(center, baseExtent.width(),
                                   baseExtent.width() * tex_height / tex_width,
                                   rotation).scale(1 + buf / 100)
            else:
                geometry.rotate(rotation, center)
                rect = geometry.boundingBox().scaled(1 + buf / 100)
                center = RotatedRect.rotatePoint(rect.center(), rotation,
                                                 center)
                if orig_tex_height:
                    tex_height = orig_tex_height
                    tex_ratio = tex_width / tex_height
                    rect_ratio = rect.width() / rect.height()
                    if tex_ratio > rect_ratio:
                        rect = RotatedRect(center,
                                           rect.height() * tex_ratio,
                                           rect.height(), rotation)
                    else:
                        rect = RotatedRect(center, rect.width(),
                                           rect.width() / tex_ratio, rotation)
                else:
                    # fit to buffered geometry bounding box
                    rect = RotatedRect(center, rect.width(), rect.height(),
                                       rotation)
                    tex_height = tex_width * rect.height() / rect.width()

            rect.toMapSettings(mapSettings)
            mapSettings.setOutputSize(QSize(tex_width, tex_height))

            self.controller.settings.setMapSettings(mapSettings)

            # labels
            exp_context.setFeature(feature)
            self.controller.settings.setHeaderLabel(
                header_exp.evaluate(exp_context))
            self.controller.settings.setFooterLabel(
                footer_exp.evaluate(exp_context))

            self.export(title, out_dir, feedback)

            feedback.setProgress(int(current / total * 100))

        if P_OPEN_DIRECTORY and not DEBUG_MODE:
            openDirectory(out_dir)

        return {}
Ejemplo n.º 15
0
 def single_to_multi( self ):
   vprovider = self.vlayer.dataProvider()
   allValid = True
   geomType = self.singleToMultiGeom( vprovider.geometryType() )
   writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
                                 geomType, vprovider.crs() )
   inFeat = QgsFeature()
   outFeat = QgsFeature()
   inGeom = QgsGeometry()
   outGeom = QgsGeometry()
   index = vprovider.fieldNameIndex( self.myField )
   if not index == -1:
     unique = ftools_utils.getUniqueValues( vprovider, int( index ) )
   else:
     unique = [ "" ]
   nFeat = vprovider.featureCount() * len( unique )
   nElement = 0
   self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
   self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
   merge_all = self.myField == "--- " + self.tr( "Merge all" ) + " ---"
   if not len( unique ) == self.vlayer.featureCount() or merge_all:
     for i in unique:
       # Strip spaces for strings, so "  A " and "A" will be grouped
       # TODO: Make this optional (opt-out to keep it easy for beginners)
       if isinstance( i, basestring ):
         iMod = i.strip()
       else:
         iMod = i
       multi_feature= []
       first = True
       fit = vprovider.getFeatures()
       while fit.nextFeature( inFeat ):
         atMap = inFeat.attributes()
         if not merge_all:
           idVar = atMap[ index ]
           if isinstance( idVar, basestring ):
             idVarMod = idVar.strip()
           else:
             idVarMod = idVar
         else:
           idVarMod = ""
         if idVarMod == iMod or merge_all:
           if first:
             atts = atMap
             first = False
           inGeom = QgsGeometry( inFeat.geometry() )
           vType = inGeom.type()
           feature_list = self.extractAsMulti( inGeom )
           multi_feature.extend( feature_list )
         nElement += 1
         self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ),  nElement )
       if not first:
         outFeat.setAttributes( atts )
         outGeom = QgsGeometry( self.convertGeometry( multi_feature, vType ) )
         if not outGeom.isGeosValid():
           allValid = "valid_error"
         outFeat.setGeometry( outGeom )
         writer.addFeature( outFeat )
     del writer
   else:
     return "attr_error"
   return allValid
Ejemplo n.º 16
0
    def in_mask(self, feature, srid=None):
        if feature is None:  # expression overview
            return False

        if self.layer is None:
            return False

        try:
            # layer is not None but destroyed ?
            self.layer.id()
        except:
            self.reset_mask_layer()
            return False

        # mask layer empty due to unloaded memlayersaver plugin > no filtering
        if self.layer.featureCount() == 0:
            return True

        mask_geom, bbox = self.mask_geometry()
        geom = QgsGeometry(feature.geometry())
        if not geom.isGeosValid():
            geom = geom.buffer(0.0, 1)

        if geom is None:
            return False

        if srid is not None and self.layer.crs().postgisSrid() != srid:
            src_crs = QgsCoordinateReferenceSystem(srid)
            dest_crs = self.layer.crs()
            xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance())
            try:
                geom.transform(xform)
            except:
                # transformation error. Check layer projection.
                pass

        if geom.type() == QgsWkbTypes.PolygonGeometry:
            if self.parameters.polygon_mask_method == 2 and not self.has_point_on_surface:
                self.parameters.polygon_mask_method = 1

            if self.parameters.polygon_mask_method == 0:
                # this method can only work when no geometry simplification is involved
                return (mask_geom.overlaps(geom) or mask_geom.contains(geom))
            elif self.parameters.polygon_mask_method == 1:
                # the fastest method, but with possible inaccuracies
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.centroid())
            elif self.parameters.polygon_mask_method == 2:
                # will always work
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.pointOnSurface())
            else:
                return False
        elif geom.type() == QgsWkbTypes.LineGeometry:
            if self.parameters.line_mask_method == 0:
                return mask_geom.intersects(geom)
            elif self.parameters.line_mask_method == 1:
                return mask_geom.contains(geom)
            else:
                return False
        elif geom.type() == QgsWkbTypes.PointGeometry:
            return mask_geom.intersects(geom)
        else:
            return False
Ejemplo n.º 17
0
    def compute(self, inName, joinName, outName, summary, sumList, keep, progressBar):
        layer1 = ftools_utils.getVectorLayerByName(inName)
        provider1 = layer1.dataProvider()
        fieldList1 = ftools_utils.getFieldList(layer1)

        layer2 = ftools_utils.getVectorLayerByName(joinName)
        provider2 = layer2.dataProvider()

        fieldList2 = ftools_utils.getFieldList(layer2)
        fieldList = QgsFields()
        if provider1.crs() != provider2.crs():
            QMessageBox.warning(self, self.tr("CRS warning!"), self.tr("Warning: Input layers have non-matching CRS.\nThis may cause unexpected results."))
        if not summary:
            fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList2)
            seq = range(0, len(fieldList1) + len(fieldList2))
            fieldList1.extend(fieldList2)
            fieldList1 = dict(zip(seq, fieldList1))
        else:
            numFields = {}
            for j in xrange(len(fieldList2)):
                if fieldList2[j].type() == QVariant.Int or fieldList2[j].type() == QVariant.Double:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + unicode(fieldList2[j].name()), QVariant.Double, "real", 24, 16, self.tr("Summary field"))
                        fieldList.append(field)
            field = QgsField("COUNT", QVariant.Double, "real", 24, 16, self.tr("Summary field"))
            fieldList.append(field)
            fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList)
            fieldList1.extend(fieldList)
            seq = range(0, len(fieldList1))
            fieldList1 = dict(zip(seq, fieldList1))

        sRs = provider1.crs()
        progressBar.setValue(13)
        check = QFile(self.shapefileName)
        if check.exists():
            if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName):
                QMessageBox.warning(
                    self, self.tr('Error deleting shapefile'),
                    self.tr("Can't delete existing shapefile\n%s") % (self.shapefileName))
                return False
        fields = QgsFields()
        for f in fieldList1.values():
            fields.append(f)
        writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, provider1.geometryType(), sRs)
        #writer = QgsVectorFileWriter(outName, "UTF-8", fieldList1, provider1.geometryType(), sRs)
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()
        progressBar.setValue(15)
        start = 15.00
        add = 85.00 / provider1.featureCount()

        index = ftools_utils.createIndex(provider2)

        # cache all features from provider2 to avoid huge number of feature requests in the inner loop
        mapP2 = {}
        for f in provider2.getFeatures():
            mapP2[f.id()] = QgsFeature(f)

        fit1 = provider1.getFeatures()
        while fit1.nextFeature(inFeat):
            inGeom = inFeat.geometry()
            atMap1 = inFeat.attributes()
            outFeat.setGeometry(inGeom)
            none = True
            joinList = []
            if inGeom.type() == QGis.Point:
                #(check, joinList) = layer2.featuresInRectangle(inGeom.buffer(10,2).boundingBox(), True, True)
                #layer2.select(inGeom.buffer(10,2).boundingBox(), False)
                #joinList = layer2.selectedFeatures()
                joinList = index.intersects(inGeom.buffer(10, 2).boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            else:
                #(check, joinList) = layer2.featuresInRectangle(inGeom.boundingBox(), True, True)
                #layer2.select(inGeom.boundingBox(), False)
                #joinList = layer2.selectedFeatures()
                joinList = index.intersects(inGeom.boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            if check == 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]  # cached feature from provider2
                    if inGeom.intersects(inFeatB.geometry()):
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])
                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == "SUM":
                                atMap.append(sum(filter_null(numFields[j])))
                            elif k == "MEAN":
                                try:
                                    nn_count = sum(1 for _ in filter_null(numFields[j]))
                                    atMap.append(sum(filter_null(numFields[j])) / nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == "MIN":
                                try:
                                    atMap.append(min(filter_null(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == "MED":
                                atMap.append(myself(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(filter_null(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())
            if keep: # keep all records
                writer.addFeature(outFeat)
            else: # keep only matching records
                if not none:
                    writer.addFeature(outFeat)
            start = start + add
            progressBar.setValue(start)
        del writer
        return True
Ejemplo n.º 18
0
    def getMatchingFeatures(self, geometry, contains, singleSelect):
        newFeatures = []
        if geometry.type() != QgsWkbTypes.PolygonGeometry:
            return newFeatures

        layer = self.canvas.currentLayer()
        if layer is None:
            return newFeatures

        selectGeomTrans = QgsGeometry(geometry)
        try:
            ct = QgsCoordinateTransform(self.canvas.mapSettings().destinationCrs(), layer.crs(), QgsProject.instance())
            if not ct.isShortCircuited() and selectGeomTrans.type() == QgsWkbTypes.PolygonGeometry:
                poly = selectGeomTrans.asPolygon()
                if len(poly) == 1 and len(poly[0]) == 5:
                    ringIn = poly[0]
                    ringOut = []
                    ringOut.append(ringIn[0])
                    i = 1
                    for j in range(1, 5):
                        v = QgsVector((ringIn[j] - ringIn[j - 1]) / 10.0)
                        for k in range(9):
                            ringOut.append(ringOut[i - 1] + v)
                            i += 1
                        ringOut.append(ringIn[j])
                        i += 1
                    selectGeomTrans = QgsGeometry.fromPolygonXY([ringOut])

            selectGeomTrans.transform(ct)
        except QgsCsException as e:
            QgsMessageLog.logMessage("Selection extends beyond layer's coordinate system")
            return newFeatures

        context = QgsRenderContext.fromMapSettings(self.canvas.mapSettings())
        context.expressionContext().appendScope(QgsExpressionContextUtils.layerScope(layer))

        r = None
        if layer.renderer():
            r = layer.renderer().clone()
            r.startRender(context, layer.fields())

        request = QgsFeatureRequest()
        request.setFilterRect(selectGeomTrans.boundingBox())
        request.setFlags(QgsFeatureRequest.ExactIntersect)

        if r:
            request.setSubsetOfAttributes(r.usedAttributes(context), layer.fields())
        else:
            request.setSubsetOfAttributes([])

        closestFeatureId = 0
        foundSingleFeature = False
        closestFeatureDist = sys.float_info.max
        for f in layer.getFeatures(request):
            context.expressionContext().setFeature(f)
            if r and  not r.willRenderFeature(f, context):
                continue

            g = f.geometry()
            if contains:
                if not selectGeomTrans.contains(g):
                    continue

            else:
                if not selectGeomTrans.intersects(g):
                    continue

            if singleSelect:
                foundSingleFeature = True
                distance = g.distance(selectGeomTrans)
                if distance <= closestFeatureDist:
                    closestFeatureDist = distance
                    closestFeatureId = f.id()
            else:
                newFeatures.append(f.id())

        if singleSelect and foundSingleFeature:
            newFeatures.append(closestFeatureId)

        if r:
            r.stopRender(context)

        return newFeatures
Ejemplo n.º 19
0
class GeometryCopier:

    def __init__(self, iface):
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/python/plugins/geometry_copier"
        # initialize locale
        locale_path = ""
        if sip.getapi("QVariant") > 1:
            # new API style
            locale = QSettings().value("locale/userLocale")[0:2]
        else:
            # the old API style
            locale = QSettings().value("locale/userLocale").toString()[0:2]

        if QFileInfo(self.plugin_dir).exists():
            locale_path = self.plugin_dir + "/i18n/geometry_copier_" + locale + ".qm"

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

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

    def initGui(self):
        # Create action that will start plugin configuration
        self.copy_action = QAction(
            QIcon(':/plugins/geometrycopier/mActionEditCopyGeom.png'),
            self.tr(u"Copy geometry"), self.iface.mainWindow())

        self.insert_action = QAction(
            QIcon(':/plugins/geometrycopier/mActionEditPasteGeom.png'),
            self.tr(u"Insert geometry"), self.iface.mainWindow())

        # connect the action to the run method
        QObject.connect(self.copy_action, SIGNAL("triggered()"), self.copy_geometry)
        QObject.connect(self.insert_action, SIGNAL("triggered()"), self.insert_geometry)

        # Add hotkeys
        self.iface.registerMainWindowAction(self.copy_action, "F7")
        self.iface.registerMainWindowAction(self.insert_action, "F8")

        # Add toolbar button and menu item
        self.iface.digitizeToolBar().addAction(self.copy_action)
        self.iface.digitizeToolBar().addAction(self.insert_action)
        self.iface.addPluginToVectorMenu(u"&Geometry copier", self.copy_action)
        self.iface.addPluginToVectorMenu(u"&Geometry copier", self.insert_action)

        # Add global signals
        QObject.connect(self.iface, SIGNAL('currentLayerChanged(QgsMapLayer *)'), self.check_buttons_state)
        QObject.connect(self.iface.mapCanvas(), SIGNAL('selectionChanged(QgsMapLayer *)'), self.check_buttons_state)
        QObject.connect(self.iface.actionToggleEditing(), SIGNAL('triggered()'), self.check_buttons_state)

        #iface.actionToggleEditing().triggered

        # init state
        self.check_buttons_state(None)

    def unload(self):
        self.iface.unregisterMainWindowAction(self.copy_action)
        self.iface.unregisterMainWindowAction(self.insert_action)
        self.iface.removePluginVectorMenu(u"&Geometry copier", self.copy_action)
        self.iface.removePluginVectorMenu(u"&Geometry copier", self.insert_action)
        self.iface.digitizeToolBar().removeAction(self.copy_action)
        self.iface.digitizeToolBar().removeAction(self.insert_action)
        QObject.disconnect(self.iface, SIGNAL('currentLayerChanged(QgsMapLayer *)'), self.check_buttons_state)
        QObject.disconnect(self.iface.mapCanvas(), SIGNAL('selectionChanged(QgsMapLayer *)'), self.check_buttons_state)
        QObject.disconnect(self.iface.actionToggleEditing(), SIGNAL('triggered()'), self.check_buttons_state)

    def check_buttons_state(self, layer=None):
        layer = self.iface.activeLayer()
        if not isinstance(layer, QgsVectorLayer):
            self.copy_action.setDisabled(True)
            self.insert_action.setDisabled(True)
            return
        sel_feat_count = layer.selectedFeatureCount()
        if sel_feat_count != 1:
            self.copy_action.setDisabled(True)
            self.insert_action.setDisabled(True)
            return
        self.copy_action.setEnabled(True)  # copy button can be pressed!
        if not layer.isEditable() or not self._geom_buffer or self._geom_buffer.type() != layer.geometryType():
            self.insert_action.setDisabled(True)
            return
        self.insert_action.setEnabled(True)  # insert button can be pressed! (type geom??)

    def copy_geometry(self):
        layer = self.iface.activeLayer()
        if not isinstance(layer, QgsVectorLayer):
            QMessageBox.information(None, self.tr('Geometry was not copied'),
                                    self.tr('Select any vector layer and feature!'))
            return
        sel_feat_count = layer.selectedFeatureCount()
        if sel_feat_count != 1:
            QMessageBox.information(None, self.tr('Geometry was not copied'),
                                    self.tr('Select one feature!'))
            return
        feature = layer.selectedFeatures()[0]
        self._geom_buffer = QgsGeometry(feature.geometry())
        self.check_buttons_state()

    def insert_geometry(self):
        layer = self.iface.activeLayer()
        if not isinstance(layer, QgsVectorLayer):
            QMessageBox.information(None, self.tr('Geometry can\'t be inserted'),
                                    self.tr('Select any vector layer and feature for inserting geom!'))
            return
        if not self._geom_buffer:
            QMessageBox.information(None, self.tr('Geometry can\'t be inserted'), self.tr('Buffer is empty!'))
            return
        if not layer.isEditable():
            QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'), self.tr('Layer is not editable!'))
            return
        if self._geom_buffer.type() != layer.geometryType():  # and layer.geometryType() != 2:
            QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'),
                                 self.tr('Target layer has other geometry type!'))
            return
        sel_feat_count = layer.selectedFeatureCount()
        if sel_feat_count != 1:
            QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'),
                                 self.tr('Select one feature for inserting geom!'))
            return
        feature = layer.selectedFeatures()[0]
        layer.changeGeometry(feature.id(), QgsGeometry(self._geom_buffer))
        self.iface.mapCanvas().refresh()

    def tr(self, text):
        return QCoreApplication.translate('GeometryCopier', text)
Ejemplo n.º 20
0
class ConflictDialog(WIDGET, BASE):

    LOCAL, REMOTE, DELETE = 1, 2, 3

    def __init__(self, conflicts):
        super(ConflictDialog,
              self).__init__(None,
                             Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.solved = False
        self.resolvedConflicts = {}
        self.conflicts = conflicts
        self.setupUi(self)

        self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint
                            | Qt.WindowMinMaxButtonsHint)

        self.zoomButton.clicked.connect(self.zoomToFullExtent)
        self.solveButton.clicked.connect(self.solve)
        self.conflictsTree.itemClicked.connect(self.treeItemClicked)
        self.attributesTable.cellClicked.connect(self.cellClicked)
        self.solveAllLocalButton.clicked.connect(self.solveAllLocal)
        self.solveAllRemoteButton.clicked.connect(self.solveAllRemote)
        self.solveLocalButton.clicked.connect(self.solveLocal)
        self.solveRemoteButton.clicked.connect(self.solveRemote)

        self.showRemoteCheck.stateChanged.connect(self.showGeoms)
        self.showLocalCheck.stateChanged.connect(self.showGeoms)

        self.lastSelectedItem = None
        self.currentPath = None
        self.currentConflict = None
        self.theirsLayer = None
        self.oursLayer = None

        settings = QSettings()
        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(0)
        horizontalLayout.setMargin(0)
        self.mapCanvas = QgsMapCanvas()
        self.mapCanvas.setCanvasColor(Qt.white)
        self.mapCanvas.enableAntiAliasing(
            settings.value("/qgis/enable_anti_aliasing", False, type=bool))
        self.mapCanvas.useImageToRender(
            settings.value("/qgis/use_qimage_to_render", False, type=bool))
        self.mapCanvas.mapRenderer().setProjectionsEnabled(True)
        action = settings.value("/qgis/wheel_action", 0, type=float)
        zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float)
        self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action),
                                      zoomFactor)
        horizontalLayout.addWidget(self.mapCanvas)
        self.canvasWidget.setLayout(horizontalLayout)
        self.panTool = QgsMapToolPan(self.mapCanvas)
        self.mapCanvas.setMapTool(self.panTool)

        self.solveButton.setEnabled(False)
        self.solveLocalButton.setEnabled(False)
        self.solveRemoteButton.setEnabled(False)

        self.fillConflictsTree()

    def fillConflictsTree(self):
        topTreeItems = {}
        for c in self.conflicts:
            path = os.path.dirname(c.path)
            if path in topTreeItems:
                topItem = topTreeItems[path]
            else:
                topItem = QTreeWidgetItem()
                topItem.setText(0, path)
                topItem.setIcon(0, layerIcon)
                topTreeItems[path] = topItem
            conflictItem = ConflictItem(c)
            topItem.addChild(conflictItem)
        for item in list(topTreeItems.values()):
            self.conflictsTree.addTopLevelItem(item)

    def cellClicked(self, row, col):
        if col > 2:
            return
        value = self.attributesTable.item(row, col).value
        geoms = (self.oursgeom, self.theirsgeom)
        self.attributesTable.setItem(row, 4, ValueItem(value, False, geoms))
        self.attributesTable.item(row, 0).setBackgroundColor(Qt.white)
        self.attributesTable.item(row, 1).setBackgroundColor(Qt.white)
        self.attributesTable.item(row, 2).setBackgroundColor(Qt.white)
        attrib = self.attributesTable.item(row, 3).text()
        if attrib in self.conflicted:
            self.conflicted.remove(attrib)
        self.updateSolveButton()

        self.showGeoms()

    def treeItemClicked(self):
        item = self.conflictsTree.selectedItems()[0]
        if self.lastSelectedItem == item:
            return
        if isinstance(item, ConflictItem):
            self.lastSelectedItem = item
            self.currentPath = item.conflict.path
            self.updateCurrentPath()
            self.solveLocalButton.setEnabled(True)
            self.solveRemoteButton.setEnabled(True)
            self.solveButton.setEnabled(False)

    def updateCurrentPath(self):
        self.solveButton.setEnabled(False)
        self.solveLocalButton.setEnabled(False)
        self.solveRemoteButton.setEnabled(False)
        self.cleanCanvas()
        self.showFeatureAttributes()
        self.createLayers()
        self.showGeoms()
        self.zoomToFullExtent()

    def zoomToFullExtent(self):
        layers = [
            lay.extent() for lay in self.mapCanvas.layers()
            if lay.type() == lay.VectorLayer
        ]
        if layers:
            ext = layers[0]
            for layer in layers[1:]:
                ext.combineExtentWith(layer)
            self.mapCanvas.setExtent(ext)
            self.mapCanvas.refresh()

    def cleanCanvas(self):
        self.mapCanvas.setLayerSet([])
        layers = [self.oursLayer, self.theirsLayer]
        for layer in layers:
            if layer is not None:
                QgsMapLayerRegistry.instance().removeMapLayer(layer.id())
        self.oursLayer = None
        self.theirsLayer = None

    def solveAllRemote(self):
        ret = QMessageBox.warning(
            self, "Solve conflict",
            "Are you sure you want to solve all conflicts using the 'To merge' version?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if ret == QMessageBox.Yes:
            self.solved = True
            self.resolvedConflicts = {
                c.path: self.REMOTE
                for c in self.conflicts
            }
            self.close()

    def solveAllLocal(self):
        ret = QMessageBox.warning(
            self, "Solve conflict",
            "Are you sure you want to solve all conflict using the 'Local' version?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if ret == QMessageBox.Yes:
            self.solved = True
            self.resolvedConflicts = {
                c.path: self.LOCAL
                for c in self.conflicts
            }
            self.close()

    def _afterSolve(self, remove=True):
        if remove:
            parent = self.lastSelectedItem.parent()
            parent.removeChild(self.lastSelectedItem)
            self.lastSelectedItem = None
            if parent.childCount() == 0:
                self.conflictsTree.invisibleRootItem().removeChild(parent)
                if self.conflictsTree.topLevelItemCount() == 0:
                    self.solved = True
                    self.close()

        self.attributesTable.setRowCount(0)
        self.cleanCanvas()
        self.solveButton.setEnabled(False)
        self.solveLocalButton.setEnabled(False)
        self.solveRemoteButton.setEnabled(False)

    def solveLocal(self):
        self.resolvedConflicts[self.currentPath] = self.LOCAL
        self._afterSolve()

    def solveRemote(self):
        self.resolvedConflicts[self.currentPath] = self.REMOTE
        self._afterSolve()

    def solve(self):
        attribs = {}
        for i in range(self.attributesTable.rowCount()):
            value = self.attributesTable.item(i, 4).value
            name = str(self.attributesTable.item(i, 3).text())
            attribs[name] = value
        self.resolvedConflicts[self.currentPath] = attribs
        self._afterSolve()

    def updateSolveButton(self):
        self.solveButton.setEnabled(len(self.conflicted) == 0)

    def showFeatureAttributes(self):
        conflictItem = self.lastSelectedItem
        self.oursgeom = None
        self.theirsgeom = None
        geoms = (self.oursgeom, self.theirsgeom)
        self.currentConflictedAttributes = []
        attribs = list(conflictItem.origin.keys())
        self.attributesTable.setRowCount(len(attribs))

        self.conflicted = []
        for idx, name in enumerate(attribs):
            font = QFont()
            font.setBold(True)
            font.setWeight(75)
            item = QTableWidgetItem(name)
            item.setFont(font)
            self.attributesTable.setItem(idx, 3, item)

            self.attributesTable.setItem(idx, 4, ValueItem(None, False))

            try:
                values = (conflictItem.origin[name], conflictItem.local[name],
                          conflictItem.remote[name])
            except Exception:  #Local has been deleted
                self._afterSolve(False)
                self.solveModifyAndDelete(conflictItem.conflict.path,
                                          self.REMOTE)
                return
            except TypeError:  #Remote has been deleted
                self._afterSolve(False)
                self.solveModifyAndDelete(conflictItem.conflict.path,
                                          self.LOCAL)
                return
            try:
                geom = QgsGeometry.fromWkt(values[0])
            except:
                geom = None
            if geom is not None:
                self.theirsgeom = QgsGeometry().fromWkt(values[1])
                self.oursgeom = QgsGeometry.fromWkt(values[2])
                geoms = (self.oursgeom, self.theirsgeom)

            ok = values[0] == values[1] or values[1] == values[2] or values[
                0] == values[2]

            for i, v in enumerate(values):
                self.attributesTable.setItem(idx, i,
                                             ValueItem(v, not ok, geoms))

            if not ok:
                self.conflicted.append(name)
            else:
                if values[0] == values[1]:
                    newvalue = values[2]
                else:
                    newvalue = values[1]
                self.attributesTable.setItem(idx, 4,
                                             ValueItem(newvalue, False, geoms))

        self.attributesTable.resizeRowsToContents()
        self.attributesTable.horizontalHeader().setMinimumSectionSize(150)
        self.attributesTable.horizontalHeader().setStretchLastSection(True)

    def solveModifyAndDelete(self, path, modified):
        msgBox = QMessageBox()
        msgBox.setText(
            "The feature has been modified in one version and deleted in the other one.\n"
            "How do you want to solve the conflict?")
        msgBox.addButton(QPushButton('Modify'), QMessageBox.YesRole)
        msgBox.addButton(QPushButton('Delete'), QMessageBox.NoRole)
        msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole)
        ret = msgBox.exec_()
        if ret == 0:
            self.resolvedConflicts[path] = modified
            self._afterSolve()
        elif ret == 1:
            self.resolvedConflicts[path] = self.DELETE
            self._afterSolve()
        else:
            pass

    def createLayers(self):
        types = [("Point", ptOursStyle, ptTheirsStyle),
                 ("LineString", lineOursStyle, lineTheirsStyle),
                 ("Polygon", polygonOursStyle, polygonTheirsStyle)]
        if self.oursgeom is not None:
            geomtype = types[int(self.oursgeom.type())][0]
            style = types[int(self.oursgeom.type())][1]
            self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326",
                                                  "ours", "memory")
            pr = self.oursLayer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(self.oursgeom)
            pr.addFeatures([feat])
            self.oursLayer.loadNamedStyle(style)
            self.oursLayer.updateExtents()
            QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False)
        else:
            self.oursLayer = None
        if self.theirsgeom is not None:
            geomtype = types[int(self.theirsgeom.type())][0]
            style = types[int(self.theirsgeom.type())][2]
            self.theirsLayer = loadLayerNoCrsDialog(
                geomtype + "?crs=EPSG:4326", "theirs", "memory")
            pr = self.theirsLayer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(self.theirsgeom)
            pr.addFeatures([feat])
            self.theirsLayer.loadNamedStyle(style)
            self.theirsLayer.updateExtents()
            QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False)
        else:
            self.theirsLayer = None

    def showGeoms(self):
        checks = [self.showRemoteCheck, self.showLocalCheck]
        layers = [self.oursLayer, self.theirsLayer]
        toShow = []
        for lay, chk in zip(layers, checks):
            if lay is not None and chk.isChecked():
                toShow.append(lay)
        self.mapCanvas.setRenderFlag(False)
        self.mapCanvas.setLayerSet(
            [QgsMapCanvasLayer(layer) for layer in toShow])
        self.mapCanvas.setRenderFlag(True)

    def closeEvent(self, evnt):
        if not self.solved:
            ret = QMessageBox.warning(
                self, "Conflict resolution", "There are unsolved conflicts.\n"
                "Do you really want to exit and abort the sync operation?",
                QMessageBox.Yes | QMessageBox.No)
            if ret == QMessageBox.No:
                evnt.ignore()
                return

        self.cleanCanvas()
Ejemplo n.º 21
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)
        precision = self.getParameterValue(self.PRECISION)

        summary = self.getParameterValue(self.SUMMARY) == 1
        keep = self.getParameterValue(self.KEEP) == 1

        sumList = self.getParameterValue(self.STATS).lower().split(',')

        targetFields = target.fields()
        joinFields = join.fields()

        fieldList = QgsFields()

        if not summary:
            joinFields = vector.testForUniqueness(targetFields, joinFields)
            seq = list(range(len(targetFields) + len(joinFields)))
            targetFields.extend(joinFields)
            targetFields = dict(list(zip(seq, targetFields)))
        else:
            numFields = {}
            for j in range(len(joinFields)):
                if joinFields[j].type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + str(joinFields[j].name()), QVariant.Double, '', 24, 16)
                        fieldList.append(field)
            field = QgsField('count', QVariant.Double, '', 24, 16)
            fieldList.append(field)
            joinFields = vector.testForUniqueness(targetFields, fieldList)
            targetFields.extend(fieldList)
            seq = list(range(len(targetFields)))
            targetFields = dict(list(zip(seq, targetFields)))

        fields = QgsFields()
        for f in list(targetFields.values()):
            fields.append(f)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, target.wkbType(), target.crs())

        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()

        index = vector.spatialindex(join)

        mapP2 = dict()
        features = vector.features(join)
        for f in features:
            mapP2[f.id()] = QgsFeature(f)

        features = vector.features(target)
        total = 100.0 / len(features)
        for c, f in enumerate(features):
            atMap1 = f.attributes()
            outFeat.setGeometry(f.geometry())
            inGeom = vector.snapToPrecision(f.geometry(), precision)
            none = True
            joinList = []
            if inGeom.type() == QgsWkbTypes.PointGeometry:
                bbox = inGeom.buffer(10, 2).boundingBox()
            else:
                bbox = inGeom.boundingBox()
            bufferedBox = vector.bufferedBoundingBox(bbox, 0.51 * precision)
            joinList = index.intersects(bufferedBox)
            if len(joinList) > 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]
                    inGeomB = vector.snapToPrecision(inFeatB.geometry(), precision)

                    res = False
                    for predicate in predicates:
                        if predicate == 'intersects':
                            res = inGeom.intersects(inGeomB)
                        elif predicate == 'contains':
                            res = inGeom.contains(inGeomB)
                        elif predicate == 'equals':
                            res = inGeom.equals(inGeomB)
                        elif predicate == 'touches':
                            res = inGeom.touches(inGeomB)
                        elif predicate == 'overlaps':
                            res = inGeom.overlaps(inGeomB)
                        elif predicate == 'within':
                            res = inGeom.within(inGeomB)
                        elif predicate == 'crosses':
                            res = inGeom.crosses(inGeomB)
                        if res:
                            break

                    if res:
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(list(zip(seq, atMap)))
                            break
                        else:
                            for j in list(numFields.keys()):
                                numFields[j].append(atMap2[j])

                if summary and not none:
                    atMap = atMap1
                    for j in list(numFields.keys()):
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(sum(self._filterNull(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1 for _ in self._filterNull(numFields[j]))
                                    atMap.append(sum(self._filterNull(numFields[j])) / nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(min(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._median(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(list(zip(seq, atMap)))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(list(atMap.values()))

            if keep:
                writer.addFeature(outFeat)
            else:
                if not none:
                    writer.addFeature(outFeat)

            progress.setPercentage(int(c * total))
        del writer
Ejemplo n.º 22
0
 def addFeatures(self, layerid, features, fields, points=None, lines=None, polygons=None, permissions={}, add_empty=False, addToMap=True):
     """ Add DIVI layer to QGIS """
     qgis_fields = [ QgsField(field['key'], self.TYPES_MAP.get(field['type'], QVariant.String)) for field in fields ]
     #print (qgis_fields)
     #print (points, lines, polygons)
     if points is not None:
         points_pr = points.dataProvider()
         if points_pr.fields():
             points_pr.deleteAttributes(list(range(len(points_pr.fields()))))
         points_pr.addAttributes(qgis_fields)
         points.updateFields()
     if lines is not None:
         lines_pr = lines.dataProvider()
         if lines_pr.fields():
             lines_pr.deleteAttributes(list(range(len(lines_pr.fields()))))
         lines_pr.addAttributes(qgis_fields)
         lines.updateFields()
     if polygons is not None:
         polygons_pr = polygons.dataProvider()
         if polygons_pr.fields():
             polygons_pr.deleteAttributes(list(range(len(polygons_pr.fields()))))
         x = polygons_pr.addAttributes(qgis_fields)
         polygons.updateFields()
     #Lists of QGIS features
     points_list = []
     lines_list = []
     polygons_list = []
     count = float(len(features))
     points_ids = []
     lines_ids = []
     polygons_ids = []
     for i, feature in enumerate(features, start=1):
         #Geometria w formacie WKB zakodowanym przez base64
         geom = QgsGeometry()
         geom.fromWkb(b64decode(feature['geometry']))
         f = QgsFeature()
         f.setGeometry(geom)
         f.setAttributes([ feature['properties'].get(field['key']) for field in fields ])
         #Add feature to list by geometry type
         if geom.type() == QgsWkbTypes.PointGeometry:
             points_list.append(f)
             points_ids.append(feature['id'])
         elif geom.type() == QgsWkbTypes.LineGeometry:
             lines_list.append(f)
             lines_ids.append(feature['id'])
         elif geom.type() == QgsWkbTypes.PolygonGeometry:
             polygons_list.append(f)
             polygons_ids.append(feature['id'])
         else:
             continue
         if self.msgBar is not None:
             #self.msgBar.setProgress(i/count)
             pass
             QgsApplication.processEvents()
             if self.msgBar.aborted:
                 #Użytkownik anulował operację
                 return []
     #Add only layers that have features
     result = []
     register = partial(self.registerLayer, layerid=layerid, permissions=permissions,
         addToMap=addToMap, fields=fields)
     if points is not None and (points_list or add_empty):
         lyr, added = register(layer=points, features=points_list)
         result.append(lyr)
         self.ids_map[points.id()] = dict(list(zip(added, points_ids)))
     if lines is not None and (lines_list or add_empty):
         lyr, added = register(layer=lines, features=lines_list)
         result.append(lyr)
         self.ids_map[lines.id()] = dict(list(zip(added, lines_ids)))
     if polygons is not None and (polygons_list or add_empty):
         lyr, added = register(layer=polygons, features=polygons_list)
         result.append(lyr)
         self.ids_map[polygons.id()] = dict(list(zip(added, polygons_ids)))
     return result
Ejemplo n.º 23
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))

        vproviderA = vlayerA.dataProvider()

        geomType = vproviderA.geometryType()
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
                                                                      geomType, vproviderA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                for id in intersects:
                    count += 1
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerB.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if geom.intersects(tmpGeom):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if int_geom is None:
                            # There was a problem creating the intersection
                            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                   self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType() == Qgis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        writer.addFeature(outFeat)
                                    except:
                                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                               self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    writer.addFeature(outFeat)
                                except:
                                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

                # the remaining bit of inFeatA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)
                    if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))

                if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(diff_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

        length = len(vproviderA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                for id in intersects:
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerA.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if diff_geom.intersects(tmpGeom):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                        if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
                    else:
                        try:
                            # Ihis only happends if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            writer.addFeature(outFeat)
                        except:
                            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                   self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            nElement += 1

        del writer
Ejemplo n.º 24
0
def intersection(source, mask, callback=None):
    """Intersect two layers.

    Issue https://github.com/inasafe/inasafe/issues/3186

    Note : This algorithm is copied from :
    https://github.com/qgis/QGIS/blob/master/python/plugins/processing/algs/
    qgis/Intersection.py

    :param source: The vector layer to clip.
    :type source: QgsVectorLayer

    :param mask: The vector layer to use for clipping.
    :type mask: QgsVectorLayer

    :param callback: A function to all to indicate progress. The function
        should accept params 'current' (int), 'maximum' (int) and 'step' (str).
        Defaults to None.
    :type callback: function

    :return: The clip vector layer.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = intersection_steps['output_layer_name']
    output_layer_name = output_layer_name % (
        source.keywords['layer_purpose'])
    processing_step = intersection_steps['step_name']

    fields = source.fields()
    fields.extend(mask.fields())

    writer = create_memory_layer(
        output_layer_name,
        source.geometryType(),
        source.crs(),
        fields
    )

    writer.startEditing()

    # Begin copy/paste from Processing plugin.
    # Please follow their code as their code is optimized.
    # The code below is not following our coding standards because we want to
    # be able to track any diffs from QGIS easily.

    out_feature = QgsFeature()
    index = create_spatial_index(mask)

    # Todo callback
    # total = 100.0 / len(selectionA)

    for current, in_feature in enumerate(source.getFeatures()):
        # progress.setPercentage(int(current * total))
        geom = in_feature.geometry()
        attributes = in_feature.attributes()
        intersects = index.intersects(geom.boundingBox())
        for i in intersects:
            request = QgsFeatureRequest().setFilterFid(i)
            feature_mask = next(mask.getFeatures(request))
            tmp_geom = feature_mask.geometry()
            if geom.intersects(tmp_geom):
                mask_attributes = feature_mask.attributes()
                int_geom = QgsGeometry(geom.intersection(tmp_geom))
                if int_geom.wkbType() == QgsWKBTypes.Unknown\
                        or QgsWKBTypes.flatType(
                        int_geom.geometry().wkbType()) ==\
                                QgsWKBTypes.GeometryCollection:
                    int_com = geom.combine(tmp_geom)
                    int_geom = QgsGeometry()
                    if int_com:
                        int_sym = geom.symDifference(tmp_geom)
                        int_geom = QgsGeometry(int_com.difference(int_sym))
                if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                    # LOGGER.debug(
                    #     tr('GEOS geoprocessing error: One or more input '
                    #        'features have invalid geometry.'))
                    pass
                try:
                    geom_types = wkb_type_groups[
                        wkb_type_groups[int_geom.wkbType()]]
                    if int_geom.wkbType() in geom_types:
                        if int_geom.type() == source.geometryType():
                            # We got some features which have not the same
                            # kind of geometry. We want to skip them.
                            out_feature.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(attributes)
                            attrs.extend(mask_attributes)
                            out_feature.setAttributes(attrs)
                            writer.addFeature(out_feature)
                except:
                    LOGGER.debug(
                        tr('Feature geometry error: One or more output '
                           'features ignored due to invalid geometry.'))
                    continue

    # End copy/paste from Processing plugin.
    writer.commitChanges()

    writer.keywords = dict(source.keywords)
    writer.keywords['title'] = output_layer_name
    writer.keywords['layer_purpose'] = layer_purpose_exposure_summary['key']
    writer.keywords['inasafe_fields'] = dict(source.keywords['inasafe_fields'])
    writer.keywords['inasafe_fields'].update(mask.keywords['inasafe_fields'])
    writer.keywords['hazard_keywords'] = dict(mask.keywords['hazard_keywords'])
    writer.keywords['exposure_keywords'] = dict(source.keywords)
    writer.keywords['aggregation_keywords'] = dict(
        mask.keywords['aggregation_keywords'])

    check_layer(writer)
    return writer
Ejemplo n.º 25
0
class GeometryCopier:
    def __init__(self, iface):
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path(
        ) + "/python/plugins/geometry_copier"
        # initialize locale
        locale_path = ""
        if sip.getapi("QVariant") > 1:
            # new API style
            locale = QSettings().value("locale/userLocale")[0:2]
        else:
            # the old API style
            locale = QSettings().value("locale/userLocale").toString()[0:2]

        if QFileInfo(self.plugin_dir).exists():
            locale_path = self.plugin_dir + "/i18n/geometry_copier_" + locale + ".qm"

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

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

    def initGui(self):
        # Create action that will start plugin configuration
        self.copy_action = QAction(
            QIcon(':/plugins/geometrycopier/mActionEditCopyGeom.png'),
            self.tr(u"Copy geometry"), self.iface.mainWindow())

        self.insert_action = QAction(
            QIcon(':/plugins/geometrycopier/mActionEditPasteGeom.png'),
            self.tr(u"Insert geometry"), self.iface.mainWindow())

        # connect the action to the run method
        QObject.connect(self.copy_action, SIGNAL("triggered()"),
                        self.copy_geometry)
        QObject.connect(self.insert_action, SIGNAL("triggered()"),
                        self.insert_geometry)

        # Add hotkeys
        self.iface.registerMainWindowAction(self.copy_action, "F7")
        self.iface.registerMainWindowAction(self.insert_action, "F8")

        # Add toolbar button and menu item
        self.iface.digitizeToolBar().addAction(self.copy_action)
        self.iface.digitizeToolBar().addAction(self.insert_action)
        self.iface.addPluginToVectorMenu(u"&Geometry copier", self.copy_action)
        self.iface.addPluginToVectorMenu(u"&Geometry copier",
                                         self.insert_action)

        # Add global signals
        QObject.connect(self.iface,
                        SIGNAL('currentLayerChanged(QgsMapLayer *)'),
                        self.check_buttons_state)
        QObject.connect(self.iface.mapCanvas(),
                        SIGNAL('selectionChanged(QgsMapLayer *)'),
                        self.check_buttons_state)
        QObject.connect(self.iface.actionToggleEditing(),
                        SIGNAL('triggered()'), self.check_buttons_state)

        #iface.actionToggleEditing().triggered

        # init state
        self.check_buttons_state(None)

    def unload(self):
        self.iface.unregisterMainWindowAction(self.copy_action)
        self.iface.unregisterMainWindowAction(self.insert_action)
        self.iface.removePluginVectorMenu(u"&Geometry copier",
                                          self.copy_action)
        self.iface.removePluginVectorMenu(u"&Geometry copier",
                                          self.insert_action)
        self.iface.digitizeToolBar().removeAction(self.copy_action)
        self.iface.digitizeToolBar().removeAction(self.insert_action)
        QObject.disconnect(self.iface,
                           SIGNAL('currentLayerChanged(QgsMapLayer *)'),
                           self.check_buttons_state)
        QObject.disconnect(self.iface.mapCanvas(),
                           SIGNAL('selectionChanged(QgsMapLayer *)'),
                           self.check_buttons_state)
        QObject.disconnect(self.iface.actionToggleEditing(),
                           SIGNAL('triggered()'), self.check_buttons_state)

    def check_buttons_state(self, layer=None):
        layer = self.iface.activeLayer()
        if not isinstance(layer, QgsVectorLayer):
            self.copy_action.setDisabled(True)
            self.insert_action.setDisabled(True)
            return
        sel_feat_count = layer.selectedFeatureCount()
        if sel_feat_count != 1:
            self.copy_action.setDisabled(True)
            self.insert_action.setDisabled(True)
            return
        self.copy_action.setEnabled(True)  # copy button can be pressed!
        if not layer.isEditable(
        ) or not self._geom_buffer or self._geom_buffer.type(
        ) != layer.geometryType():
            self.insert_action.setDisabled(True)
            return
        self.insert_action.setEnabled(
            True)  # insert button can be pressed! (type geom??)

    def copy_geometry(self):
        layer = self.iface.activeLayer()
        if not isinstance(layer, QgsVectorLayer):
            QMessageBox.information(
                None, self.tr('Geometry was not copied'),
                self.tr('Select any vector layer and feature!'))
            return
        sel_feat_count = layer.selectedFeatureCount()
        if sel_feat_count != 1:
            QMessageBox.information(None, self.tr('Geometry was not copied'),
                                    self.tr('Select one feature!'))
            return
        feature = layer.selectedFeatures()[0]
        self._geom_buffer = QgsGeometry(feature.geometry())
        self.check_buttons_state()

    def insert_geometry(self):
        layer = self.iface.activeLayer()
        if not isinstance(layer, QgsVectorLayer):
            QMessageBox.information(
                None, self.tr('Geometry can\'t be inserted'),
                self.tr(
                    'Select any vector layer and feature for inserting geom!'))
            return
        if not self._geom_buffer:
            QMessageBox.information(None,
                                    self.tr('Geometry can\'t be inserted'),
                                    self.tr('Buffer is empty!'))
            return
        if not layer.isEditable():
            QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'),
                                 self.tr('Layer is not editable!'))
            return
        if self._geom_buffer.type() != layer.geometryType(
        ):  # and layer.geometryType() != 2:
            QMessageBox.critical(
                None, self.tr('Geometry can\'t be inserted'),
                self.tr('Target layer has other geometry type!'))
            return
        sel_feat_count = layer.selectedFeatureCount()
        if sel_feat_count != 1:
            QMessageBox.critical(
                None, self.tr('Geometry can\'t be inserted'),
                self.tr('Select one feature for inserting geom!'))
            return
        feature = layer.selectedFeatures()[0]
        layer.changeGeometry(feature.id(), QgsGeometry(self._geom_buffer))
        self.iface.mapCanvas().refresh()

    def tr(self, text):
        return QCoreApplication.translate('GeometryCopier', text)
Ejemplo n.º 26
0
    def processAlgorithm(self, parameters, context, feedback):
        if DEBUG_MODE:
            logMessage("processAlgorithm(): {}".format(
                self.__class__.__name__))

        source = self.parameterAsSource(parameters, self.INPUT, context)
        source_layer = self.parameterAsLayer(parameters, self.INPUT, context)
        title_field = self.parameterAsString(parameters, self.TITLE_FIELD,
                                             context)
        cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context)
        fixed_scale = self.parameterAsEnum(parameters, self.SCALE,
                                           context)  # == 1
        buf = self.parameterAsDouble(parameters, self.BUFFER, context)
        tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context)
        orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT,
                                              context)
        out_dir = self.parameterAsString(parameters, self.OUTPUT, context)

        mapSettings = self.controller.settings.mapSettings
        baseExtent = self.controller.settings.baseExtent
        rotation = mapSettings.rotation()
        orig_size = mapSettings.outputSize()

        if cf_filter:
            #TODO: FIX ME
            #cf_layer = QgsMemoryProviderUtils.createMemoryLayer("current feature",
            #                                                    source_layer.fields(),
            #                                                    source_layer.wkbType(),
            #                                                    source_layer.crs())

            doc = QDomDocument("qgis")
            source_layer.exportNamedStyle(doc)

            orig_layers = mapSettings.layers()

        total = source.featureCount()
        for current, feature in enumerate(source.getFeatures()):
            if feedback.isCanceled():
                break

            if cf_filter:
                cf_layer = QgsMemoryProviderUtils.createMemoryLayer(
                    "current feature", source_layer.fields(),
                    source_layer.wkbType(), source_layer.crs())
                cf_layer.startEditing()
                cf_layer.addFeature(feature)
                cf_layer.commitChanges()

                cf_layer.importNamedStyle(doc)

                layers = [
                    cf_layer if lyr == source_layer else lyr
                    for lyr in orig_layers
                ]
                mapSettings.setLayers(layers)

            title = feature.attribute(title_field)
            feedback.setProgressText("({}/{}) Exporting {}...".format(
                current + 1, total, title))

            # extent
            geometry = QgsGeometry(feature.geometry())
            geometry.transform(self.transform)
            center = geometry.centroid().asPoint()

            if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry:
                tex_height = orig_tex_height or int(
                    tex_width * orig_size.height() / orig_size.width())
                rect = RotatedRect(center, baseExtent.width(),
                                   baseExtent.width() * tex_height / tex_width,
                                   rotation).scale(1 + buf / 100)
            else:
                geometry.rotate(rotation, center)
                rect = geometry.boundingBox().scaled(1 + buf / 100)
                center = RotatedRect.rotatePoint(rect.center(), rotation,
                                                 center)
                if orig_tex_height:
                    tex_height = orig_tex_height
                    tex_ratio = tex_width / tex_height
                    rect_ratio = rect.width() / rect.height()
                    if tex_ratio > rect_ratio:
                        rect = RotatedRect(center,
                                           rect.height() * tex_ratio,
                                           rect.height(), rotation)
                    else:
                        rect = RotatedRect(center, rect.width(),
                                           rect.width() / tex_ratio, rotation)
                else:
                    # fit to buffered geometry bounding box
                    rect = RotatedRect(center, rect.width(), rect.height(),
                                       rotation)
                    tex_height = tex_width * rect.height() / rect.width()

            rect.toMapSettings(mapSettings)
            mapSettings.setOutputSize(QSize(tex_width, tex_height))

            self.controller.settings.setMapSettings(mapSettings)

            self.export(title, out_dir, feedback)

            feedback.setProgress(int(current / total * 100))

        return {}
class ConflictDialog(WIDGET, BASE):

    LOCAL, REMOTE, DELETE = 1,2, 3

    def __init__(self, conflicts):
        super(ConflictDialog, self).__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.solved = False
        self.resolvedConflicts = {}
        self.conflicts = conflicts
        self.setupUi(self)

        self.setWindowFlags(self.windowFlags() |
                              Qt.WindowSystemMenuHint |
                              Qt.WindowMinMaxButtonsHint)

        self.zoomButton.clicked.connect(self.zoomToFullExtent)
        self.solveButton.clicked.connect(self.solve)
        self.conflictsTree.itemClicked.connect(self.treeItemClicked)
        self.attributesTable.cellClicked.connect(self.cellClicked)
        self.solveAllLocalButton.clicked.connect(self.solveAllLocal)
        self.solveAllRemoteButton.clicked.connect(self.solveAllRemote)
        self.solveLocalButton.clicked.connect(self.solveLocal)
        self.solveRemoteButton.clicked.connect(self.solveRemote)

        self.showRemoteCheck.stateChanged.connect(self.showGeoms)
        self.showLocalCheck.stateChanged.connect(self.showGeoms)

        self.lastSelectedItem = None
        self.currentPath = None
        self.currentConflict = None
        self.theirsLayer = None
        self.oursLayer = None

        settings = QSettings()
        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(0)
        horizontalLayout.setMargin(0)
        self.mapCanvas = QgsMapCanvas()
        self.mapCanvas.setCanvasColor(Qt.white)
        self.mapCanvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool))
        self.mapCanvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool))
        self.mapCanvas.mapRenderer().setProjectionsEnabled(True)
        action = settings.value("/qgis/wheel_action", 0, type = float)
        zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float)
        self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor)
        horizontalLayout.addWidget(self.mapCanvas)
        self.canvasWidget.setLayout(horizontalLayout)
        self.panTool = QgsMapToolPan(self.mapCanvas)
        self.mapCanvas.setMapTool(self.panTool)

        self.solveButton.setEnabled(False)
        self.solveLocalButton.setEnabled(False)
        self.solveRemoteButton.setEnabled(False)

        self.fillConflictsTree()

    def fillConflictsTree(self):
        topTreeItems = {}
        for c in self.conflicts:
            path = os.path.dirname(c.path)
            if path in topTreeItems:
                topItem = topTreeItems[path]
            else:
                topItem = QTreeWidgetItem()
                topItem.setText(0, path)
                topItem.setIcon(0, layerIcon)
                topTreeItems[path] = topItem
            conflictItem = ConflictItem(c)
            topItem.addChild(conflictItem)
        for item in list(topTreeItems.values()):
            self.conflictsTree.addTopLevelItem(item)

    def cellClicked(self, row, col):
        if col > 2:
            return
        value = self.attributesTable.item(row, col).value
        geoms = (self.oursgeom, self.theirsgeom)
        self.attributesTable.setItem(row, 4, ValueItem(value, False, geoms));
        self.attributesTable.item(row, 0).setBackgroundColor(Qt.white);
        self.attributesTable.item(row, 1).setBackgroundColor(Qt.white);
        self.attributesTable.item(row, 2).setBackgroundColor(Qt.white);
        attrib = self.attributesTable.item(row, 3).text()
        if attrib in self.conflicted:
            self.conflicted.remove(attrib)
        self.updateSolveButton()

        self.showGeoms()

    def treeItemClicked(self):
        item = self.conflictsTree.selectedItems()[0]
        if self.lastSelectedItem == item:
            return
        if isinstance(item, ConflictItem):
            self.lastSelectedItem = item
            self.currentPath = item.conflict.path
            self.updateCurrentPath()
            self.solveLocalButton.setEnabled(True)
            self.solveRemoteButton.setEnabled(True)
            self.solveButton.setEnabled(False)

    def updateCurrentPath(self):
        self.solveButton.setEnabled(False)
        self.solveLocalButton.setEnabled(False)
        self.solveRemoteButton.setEnabled(False)
        self.cleanCanvas()
        self.showFeatureAttributes()
        self.createLayers()
        self.showGeoms()
        self.zoomToFullExtent()

    def zoomToFullExtent(self):
        layers = [lay.extent() for lay in self.mapCanvas.layers() if lay.type() == lay.VectorLayer]
        if layers:
            ext = layers[0]
            for layer in  layers[1:]:
                ext.combineExtentWith(layer)
            self.mapCanvas.setExtent(ext)
            self.mapCanvas.refresh()

    def cleanCanvas(self):
        self.mapCanvas.setLayerSet([])
        layers = [self.oursLayer, self.theirsLayer]
        for layer in layers:
            if layer is not None:
                QgsMapLayerRegistry.instance().removeMapLayer(layer.id())
        self.oursLayer = None
        self.theirsLayer = None

    def solveAllRemote(self):
        ret = QMessageBox.warning(self, "Solve conflict",
                                "Are you sure you want to solve all conflicts using the 'To merge' version?",
                                QMessageBox.Yes | QMessageBox.No,
                                QMessageBox.Yes);
        if ret == QMessageBox.Yes:
            self.solved = True
            self.resolvedConflicts = {c.path:self.REMOTE for c in self.conflicts}
            self.close()

    def solveAllLocal(self):
        ret = QMessageBox.warning(self, "Solve conflict",
            "Are you sure you want to solve all conflict using the 'Local' version?",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.Yes);
        if ret == QMessageBox.Yes:
            self.solved = True
            self.resolvedConflicts = {c.path:self.LOCAL for c in self.conflicts}
            self.close()


    def _afterSolve(self, remove = True):
        if remove:
            parent = self.lastSelectedItem.parent()
            parent.removeChild(self.lastSelectedItem)
            self.lastSelectedItem = None
            if parent.childCount() == 0:
                self.conflictsTree.invisibleRootItem().removeChild(parent)
                if self.conflictsTree.topLevelItemCount() == 0:
                    self.solved = True
                    self.close()

        self.attributesTable.setRowCount(0)
        self.cleanCanvas()
        self.solveButton.setEnabled(False)
        self.solveLocalButton.setEnabled(False)
        self.solveRemoteButton.setEnabled(False)

    def solveLocal(self):
        self.resolvedConflicts[self.currentPath] = self.LOCAL
        self._afterSolve()

    def solveRemote(self):
        self.resolvedConflicts[self.currentPath] = self.REMOTE
        self._afterSolve()

    def solve(self):
        attribs = {}
        for i in range(self.attributesTable.rowCount()):
            value = self.attributesTable.item(i, 4).value
            name = str(self.attributesTable.item(i, 3).text())
            attribs[name] = value
        self.resolvedConflicts[self.currentPath] = attribs
        self._afterSolve()


    def updateSolveButton(self):
        self.solveButton.setEnabled(len(self.conflicted) == 0)

    def showFeatureAttributes(self):
        conflictItem = self.lastSelectedItem
        self.oursgeom = None
        self.theirsgeom = None
        geoms = (self.oursgeom, self.theirsgeom)
        self.currentConflictedAttributes = []
        attribs = list(conflictItem.origin.keys())
        self.attributesTable.setRowCount(len(attribs))

        self.conflicted = []
        for idx, name in enumerate(attribs):
            font = QFont()
            font.setBold(True)
            font.setWeight(75)
            item = QTableWidgetItem(name)
            item.setFont(font)
            self.attributesTable.setItem(idx, 3, item);

            self.attributesTable.setItem(idx, 4, ValueItem(None, False));

            try:
                values = (conflictItem.origin[name], conflictItem.local[name], conflictItem.remote[name])
            except Exception: #Local has been deleted
                self._afterSolve(False)
                self.solveModifyAndDelete(conflictItem.conflict.path, self.REMOTE)
                return
            except TypeError: #Remote has been deleted
                self._afterSolve(False)
                self.solveModifyAndDelete(conflictItem.conflict.path,self.LOCAL)
                return
            try:
                geom = QgsGeometry.fromWkt(values[0])
            except:
                geom = None
            if geom is not None:
                self.theirsgeom = QgsGeometry().fromWkt(values[1])
                self.oursgeom = QgsGeometry.fromWkt(values[2])
                geoms = (self.oursgeom, self.theirsgeom)

            ok = values[0] == values[1] or values[1] == values[2] or values[0] == values[2]

            for i, v in enumerate(values):
                self.attributesTable.setItem(idx, i, ValueItem(v, not ok, geoms));

            if not ok:
                self.conflicted.append(name)
            else:
                if values[0] == values[1]:
                    newvalue = values[2]
                else:
                    newvalue = values[1]
                self.attributesTable.setItem(idx, 4, ValueItem(newvalue, False, geoms));

        self.attributesTable.resizeRowsToContents()
        self.attributesTable.horizontalHeader().setMinimumSectionSize(150)
        self.attributesTable.horizontalHeader().setStretchLastSection(True)


    def solveModifyAndDelete(self, path, modified):
        msgBox = QMessageBox()
        msgBox.setText("The feature has been modified in one version and deleted in the other one.\n"
                       "How do you want to solve the conflict?")
        msgBox.addButton(QPushButton('Modify'), QMessageBox.YesRole)
        msgBox.addButton(QPushButton('Delete'), QMessageBox.NoRole)
        msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole)
        ret = msgBox.exec_()
        if ret == 0:
            self.resolvedConflicts[path] = modified
            self._afterSolve()
        elif ret == 1:
            self.resolvedConflicts[path] = self.DELETE
            self._afterSolve()
        else:
            pass

    def createLayers(self):
        types = [("Point", ptOursStyle, ptTheirsStyle),
                  ("LineString", lineOursStyle, lineTheirsStyle),
                  ("Polygon", polygonOursStyle, polygonTheirsStyle)]
        if self.oursgeom is not None:
            geomtype = types[int(self.oursgeom.type())][0]
            style = types[int(self.oursgeom.type())][1]
            self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "ours", "memory")
            pr = self.oursLayer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(self.oursgeom)
            pr.addFeatures([feat])
            self.oursLayer.loadNamedStyle(style)
            self.oursLayer.updateExtents()
            QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False)
        else:
            self.oursLayer = None
        if self.theirsgeom is not None:
            geomtype = types[int(self.theirsgeom.type())][0]
            style = types[int(self.theirsgeom.type())][2]
            self.theirsLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "theirs", "memory")
            pr = self.theirsLayer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(self.theirsgeom)
            pr.addFeatures([feat])
            self.theirsLayer.loadNamedStyle(style)
            self.theirsLayer.updateExtents()
            QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False)
        else:
            self.theirsLayer = None

    def showGeoms(self):
        checks = [self.showRemoteCheck, self.showLocalCheck]
        layers = [self.oursLayer, self.theirsLayer]
        toShow = []
        for lay, chk in zip(layers, checks):
            if lay is not None and chk.isChecked():
                toShow.append(lay)
        self.mapCanvas.setRenderFlag(False)
        self.mapCanvas.setLayerSet([QgsMapCanvasLayer(layer) for layer in toShow])
        self.mapCanvas.setRenderFlag(True)


    def closeEvent(self, evnt):
        if not self.solved:
            ret = QMessageBox.warning(self, "Conflict resolution",
                                  "There are unsolved conflicts.\n"
                                  "Do you really want to exit and abort the sync operation?",
                                  QMessageBox.Yes | QMessageBox.No)
            if ret == QMessageBox.No:
                evnt.ignore()
                return

        self.cleanCanvas()
    def load_complex_gml(self, xml_uri, is_remote, attributes = {}, geometry_mapping = None, logger = None, swap_xy = False):
        """
        :param xml_uri: the XML URI
        :param is_remote: True if it has to be fetched by http
        :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) }
        :param geometry_mapping: XPath expression to a gml geometry node
        :param swap_xy: True if X/Y coordinates must be swapped
        :returns: the created layer
        """
        if is_remote:
            xml = remote_open_from_qgis(xml_uri)
        else:
            # Open the file in binary mode, this means returning bytes
            # instead of a string whose encoding would have to be interpreted
            # it is up to the XML parser to determine which encoding it is
            xml = open(xml_uri, 'rb')
        src = ComplexFeatureSource(xml, attributes, geometry_mapping, logger)

        attr_list = [ (k, v[1]) for k, v in attributes.items() ]
        
        # first feature
        id, fid, g, xml, attrs = next(src.getFeatures())
        qgsgeom = None
        if g is None:
            layer = self._create_layer('none', None, attr_list, src.title)
        else:
            wkb, srid = g
            qgsgeom = QgsGeometry()
            qgsgeom.fromWkb(wkb)
            if qgsgeom and qgsgeom.type() == QgsWkbTypes.PointGeometry:
                layer = self._create_layer('point', srid, attr_list, src.title + " (points)")
            elif qgsgeom and qgsgeom.type() == QgsWkbTypes.LineGeometry:
                layer = self._create_layer('linestring', srid, attr_list, src.title + " (lines)")
            elif qgsgeom and qgsgeom.type() == QgsWkbTypes.PolygonGeometry:
                layer = self._create_layer('polygon', srid, attr_list, src.title + " (polygons)")

        # add metadata
        self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping)

        # collect features
        features = []
        for id, fid, g, xml, attrs in src.getFeatures():
            qgsgeom = None
            wkb, srid = g
            qgsgeom = QgsGeometry()
            qgsgeom.fromWkb(wkb)
            if qgsgeom and qgsgeom.type() == QgsWkbTypes.PointGeometry:
                if swap_xy:
                    p = qgsgeom.asPoint()
                    qgsgeom = QgsGeometry.fromPoint(QgsPointXY(p[1], p[0]))
            elif qgsgeom and qgsgeom.type() == QgsWkbTypes.LineGeometry:
                if swap_xy:
                    pl = qgsgeom.asPolyline()
                    qgsgeom = QgsGeometry.fromPolyline([QgsPointXY(p[1],p[0]) for p in pl])
            elif qgsgeom and qgsgeom.type() == QgsWkbTypes.PolygonGeometry:
                if swap_xy:
                    pl = qgsgeom.asPolygon()
                    qgsgeom = QgsGeometry.fromPolygon([[QgsPointXY(p[1],p[0]) for p in r] for r in pl])

            f = QgsFeature(layer.dataProvider().fields(), id)
            if qgsgeom:
                f.setGeometry(qgsgeom)
            f.setAttribute("id", str(id))
            f.setAttribute("fid", fid)
            f.setAttribute("_xml_", ET.tostring(xml).decode('utf8'))
            for k, v in attrs.items():
                r = f.setAttribute(k, v)
            features.append(f)

        # write features
        if len(features) > 0:
            layer.dataProvider().addFeatures(features)

        return layer
Ejemplo n.º 29
0
 def single_to_multi(self):
     vprovider = self.vlayer.dataProvider()
     allValid = True
     geomType = self.singleToMultiGeom(vprovider.geometryType())
     writer = QgsVectorFileWriter(self.myName, self.myEncoding, vprovider.fields(),
                                  geomType, vprovider.crs())
     inFeat = QgsFeature()
     outFeat = QgsFeature()
     inGeom = QgsGeometry()
     outGeom = QgsGeometry()
     index = vprovider.fieldNameIndex(self.myField)
     if not index == -1:
         unique = ftools_utils.getUniqueValues(vprovider, int(index))
     else:
         unique = [""]
     nFeat = vprovider.featureCount() * len(unique)
     nElement = 0
     self.emit(SIGNAL("runStatus( PyQt_PyObject )"), 0)
     self.emit(SIGNAL("runRange( PyQt_PyObject )"), (0, nFeat))
     merge_all = self.myField == "--- " + self.tr("Merge all") + " ---"
     if not len(unique) == self.vlayer.featureCount() or merge_all:
         for i in unique:
             # Strip spaces for strings, so "  A " and "A" will be grouped
             # TODO: Make this optional (opt-out to keep it easy for beginners)
             if isinstance(i, basestring):
                 iMod = i.strip()
             else:
                 iMod = i
             multi_feature = []
             first = True
             fit = vprovider.getFeatures()
             while fit.nextFeature(inFeat):
                 atMap = inFeat.attributes()
                 if not merge_all:
                     idVar = atMap[index]
                     if isinstance(idVar, basestring):
                         idVarMod = idVar.strip()
                     else:
                         idVarMod = idVar
                 else:
                     idVarMod = ""
                 if idVarMod == iMod or merge_all:
                     if first:
                         atts = atMap
                         first = False
                     inGeom = QgsGeometry(inFeat.geometry())
                     vType = inGeom.type()
                     feature_list = self.extractAsMulti(inGeom)
                     multi_feature.extend(feature_list)
                 nElement += 1
                 self.emit(SIGNAL("runStatus( PyQt_PyObject )"), nElement)
             if not first:
                 outFeat.setAttributes(atts)
                 outGeom = QgsGeometry(self.convertGeometry(multi_feature, vType))
                 if not outGeom.isGeosValid():
                     allValid = "valid_error"
                 outFeat.setGeometry(outGeom)
                 writer.addFeature(outFeat)
         del writer
     else:
         return "attr_error"
     return allValid
Ejemplo n.º 30
0
Archivo: Union.py Proyecto: cjmayo/QGIS
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))
        GEOS_EXCEPT = True
        FEATURE_EXCEPT = True
        vproviderA = vlayerA.dataProvider()

        fields = vector.combineVectorFields(vlayerA, vlayerB)
        names = [field.name() for field in fields]
        ProcessingLog.addToLog(ProcessingLog.LOG_INFO, unicode(names))
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
                                                                      vproviderA.geometryType(), vproviderA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    raise GeoAlgorithmExecutionException(
                        self.tr('Feature exception while computing union'))
            else:
                for id in intersects:
                    count += 1
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerB.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if geom.intersects(tmpGeom):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if int_geom is None:
                           # There was a problem creating the intersection
                            raise GeoAlgorithmExecutionException(
                                self.tr('Geometry exception while computing '
                                        'intersection'))
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                        try:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                        except Exception as err:
                            raise GeoAlgorithmExecutionException(
                                self.tr('Feature exception while computing union'))

                try:
                    # the remaining bit of inFeatA's geometry
                    # if there is nothing left, this will just silently fail and we're good
                    diff_geom = QgsGeometry(geom)
                    if len(lstIntersectingB) != 0:
                        intB = QgsGeometry.unaryUnion(lstIntersectingB)
                        diff_geom = diff_geom.difference(intB)

                    if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                        temp_list = diff_geom.asGeometryCollection()
                        for i in temp_list:
                            if i.type() == geom.type():
                                diff_geom = QgsGeometry(i)
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except Exception as err:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Feature exception while computing union'))

        length = len(vproviderA.fields())

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except Exception as err:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Feature exception while computing union'))
            else:
                for id in intersects:
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerA.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())
                    try:
                        if diff_geom.intersects(tmpGeom):
                            add = True
                            diff_geom = QgsGeometry(
                                diff_geom.difference(tmpGeom))
                        else:
                            # Ihis only happends if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            writer.addFeature(outFeat)
                    except Exception as err:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while computing intersection'))

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except Exception as err:
                    raise err
                    FEATURE_EXCEPT = False
            nElement += 1

        del writer
        if not GEOS_EXCEPT:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                   self.tr('Geometry exception while computing intersection'))
        if not FEATURE_EXCEPT:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                   self.tr('Feature exception while computing intersection'))
Ejemplo n.º 31
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)

        summary = self.getParameterValue(self.SUMMARY) == 1
        keep = self.getParameterValue(self.KEEP) == 1

        sumList = self.getParameterValue(self.STATS).lower().split(',')

        targetProvider = target.dataProvider()
        joinProvider = join.dataProvider()

        targetFields = targetProvider.fields()
        joinFields = joinProvider.fields()

        fieldList = QgsFields()

        if not summary:
            joinFields = vector.testForUniqueness(targetFields, joinFields)
            seq = range(0, len(targetFields) + len(joinFields))
            targetFields.extend(joinFields)
            targetFields = dict(zip(seq, targetFields))
        else:
            numFields = {}
            for j in xrange(len(joinFields)):
                if joinFields[j].type() in [QVariant.Int, QVariant.Double]:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + unicode(joinFields[j].name()), QVariant.Double, '', 24, 16)
                        fieldList.append(field)
            field = QgsField('count', QVariant.Double, '', 24, 16)
            fieldList.append(field)
            joinFields = vector.testForUniqueness(targetFields, fieldList)
            targetFields.extend(fieldList)
            seq = range(0, len(targetFields))
            targetFields = dict(zip(seq, targetFields))

        fields = QgsFields()
        for f in targetFields.values():
            fields.append(f)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, targetProvider.geometryType(), targetProvider.crs())

        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()

        index = vector.spatialindex(join)

        mapP2 = dict()
        features = vector.features(join)
        for f in features:
            mapP2[f.id()] = QgsFeature(f)

        features = vector.features(target)
        total = 100.0 / len(features)
        for c, f in enumerate(features):
            inGeom = f.geometry()
            atMap1 = f.attributes()
            outFeat.setGeometry(inGeom)
            none = True
            joinList = []
            if inGeom.type() == QGis.Point:
                joinList = index.intersects(inGeom.buffer(10, 2).boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            else:
                joinList = index.intersects(inGeom.boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1

            if check == 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]
                    inGeomB = inFeatB.geometry()

                    res = False
                    for predicate in predicates:
                        if predicate == 'intersects':
                            res = inGeom.intersects(inGeomB)
                        elif predicate == 'contains':
                            res = inGeom.contains(inGeomB)
                        elif predicate == 'equals':
                            res = inGeom.equals(inGeomB)
                        elif predicate == 'touches':
                            res = inGeom.touches(inGeomB)
                        elif predicate == 'overlaps':
                            res = inGeom.overlaps(inGeomB)
                        elif predicate == 'within':
                            res = inGeom.within(inGeomB)
                        elif predicate == 'crosses':
                            res = inGeom.crosses(inGeomB)
                        if res:
                            break

                    if res:
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])

                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(sum(self._filterNull(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1 for _ in self._filterNull(numFields[j]))
                                    atMap.append(sum(self._filterNull(numFields[j])) / nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(min(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._median(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())

            if keep:
                writer.addFeature(outFeat)
            else:
                if not none:
                    writer.addFeature(outFeat)

            progress.setPercentage(int(c * total))
        del writer
Ejemplo n.º 32
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Union.INPUT2))

        vproviderA = vlayerA.dataProvider()

        geomType = vproviderA.geometryType()
        if geomType in GEOM_25D:
            raise GeoAlgorithmExecutionException(
                self.tr('Input layer has unsupported geometry type {}').format(
                    geomType))

        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(
            fields, geomType, vproviderA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
            else:
                for id in intersects:
                    count += 1
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerB.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if geom.intersects(tmpGeom):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if int_geom is None:
                            # There was a problem creating the intersection
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_INFO,
                                self.
                                tr('GEOS geoprocessing error: One or more input features have invalid geometry.'
                                   ))
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType(
                        ) == QGis.WKBUnknown or QgsWKBTypes.flatType(
                                int_geom.geometry().wkbType(
                                )) == QgsWKBTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        writer.addFeature(outFeat)
                                    except:
                                        ProcessingLog.addToLog(
                                            ProcessingLog.LOG_INFO,
                                            self.
                                            tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                                               ))
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[
                                    wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    writer.addFeature(outFeat)
                                except:
                                    ProcessingLog.addToLog(
                                        ProcessingLog.LOG_INFO,
                                        self.
                                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                                           ))

                # the remaining bit of inFeatA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)
                    if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.
                            tr('GEOS geoprocessing error: One or more input features have invalid geometry.'
                               ))

                if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(
                        diff_geom.geometry().wkbType(
                        )) == QgsWKBTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))

        length = len(vproviderA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
            else:
                for id in intersects:
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerA.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if diff_geom.intersects(tmpGeom):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                        if diff_geom.isGeosEmpty(
                        ) or not diff_geom.isGeosValid():
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_ERROR,
                                self.
                                tr('GEOS geoprocessing error: One or more input features have invalid geometry.'
                                   ))
                    else:
                        try:
                            # Ihis only happends if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            writer.addFeature(outFeat)
                        except:
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_INFO,
                                self.
                                tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                                   ))

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
            nElement += 1

        del writer
Ejemplo n.º 33
0
def intersection(source, mask, callback=None):
    """Intersect two layers.

    Issue https://github.com/inasafe/inasafe/issues/3186

    Note : This algorithm is copied from :
    https://github.com/qgis/QGIS/blob/master/python/plugins/processing/algs/
    qgis/Intersection.py

    :param source: The vector layer to clip.
    :type source: QgsVectorLayer

    :param mask: The vector layer to use for clipping.
    :type mask: QgsVectorLayer

    :param callback: A function to all to indicate progress. The function
        should accept params 'current' (int), 'maximum' (int) and 'step' (str).
        Defaults to None.
    :type callback: function

    :return: The clip vector layer.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = intersection_steps['output_layer_name']
    output_layer_name = output_layer_name % (
        source.keywords['layer_purpose'])
    processing_step = intersection_steps['step_name']

    fields = source.fields()
    fields.extend(mask.fields())

    writer = create_memory_layer(
        output_layer_name,
        source.geometryType(),
        source.crs(),
        fields
    )

    writer.startEditing()

    # Begin copy/paste from Processing plugin.
    # Please follow their code as their code is optimized.
    # The code below is not following our coding standards because we want to
    # be able to track any diffs from QGIS easily.

    out_feature = QgsFeature()
    index = create_spatial_index(mask)

    # Todo callback
    # total = 100.0 / len(selectionA)

    for current, in_feature in enumerate(source.getFeatures()):
        # progress.setPercentage(int(current * total))
        geom = in_feature.geometry()
        attributes = in_feature.attributes()
        intersects = index.intersects(geom.boundingBox())
        for i in intersects:
            request = QgsFeatureRequest().setFilterFid(i)
            feature_mask = next(mask.getFeatures(request))
            tmp_geom = feature_mask.geometry()
            if geom.intersects(tmp_geom):
                mask_attributes = feature_mask.attributes()
                int_geom = QgsGeometry(geom.intersection(tmp_geom))
                if int_geom.wkbType() == QgsWKBTypes.Unknown\
                        or QgsWKBTypes.flatType(
                        int_geom.geometry().wkbType()) ==\
                                QgsWKBTypes.GeometryCollection:
                    int_com = geom.combine(tmp_geom)
                    int_geom = QgsGeometry()
                    if int_com:
                        int_sym = geom.symDifference(tmp_geom)
                        int_geom = QgsGeometry(int_com.difference(int_sym))
                if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                    # LOGGER.debug(
                    #     tr('GEOS geoprocessing error: One or more input '
                    #        'features have invalid geometry.'))
                    pass
                try:
                    geom_types = wkb_type_groups[
                        wkb_type_groups[int_geom.wkbType()]]
                    if int_geom.wkbType() in geom_types:
                        if int_geom.type() == source.geometryType():
                            # We got some features which have not the same
                            # kind of geometry. We want to skip them.
                            out_feature.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(attributes)
                            attrs.extend(mask_attributes)
                            out_feature.setAttributes(attrs)
                            writer.addFeature(out_feature)
                except:
                    LOGGER.debug(
                        tr('Feature geometry error: One or more output '
                           'features ignored due to invalid geometry.'))
                    continue

    # End copy/paste from Processing plugin.
    writer.commitChanges()

    writer.keywords = dict(source.keywords)
    writer.keywords['title'] = output_layer_name
    writer.keywords['layer_purpose'] = layer_purpose_exposure_summary['key']
    writer.keywords['inasafe_fields'] = dict(source.keywords['inasafe_fields'])
    writer.keywords['inasafe_fields'].update(mask.keywords['inasafe_fields'])
    writer.keywords['hazard_keywords'] = dict(mask.keywords['hazard_keywords'])
    writer.keywords['exposure_keywords'] = dict(source.keywords)
    writer.keywords['aggregation_keywords'] = dict(
        mask.keywords['aggregation_keywords'])

    check_layer(writer)
    return writer
Ejemplo n.º 34
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))

        geomType = vlayerA.wkbType()
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
                                                                      geomType,
                                                                      vlayerA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA) if len(featuresA) > 0 else 1
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                for id in intersects:
                    count += 1
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerB.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if geom.intersects(tmpGeom):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if int_geom is None:
                            # There was a problem creating the intersection
                            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                   self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        # TODO: the result may have a different dimension (e.g. intersection of two polygons may result in a single point)
                        # or the result may be a collection of geometries (e.g. intersection of two polygons results in three polygons and one linestring).
                        # We need to filter out all acceptable geometries into a single (possibly multi-part) geometry - and we need
                        # to do it consistently also in the code further below

                        if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        writer.addFeature(outFeat)
                                    except:
                                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                               self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    writer.addFeature(outFeat)
                                except:
                                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

                # the remaining bit of inFeatA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)
                    if diff_geom is None:
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                               self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
                        diff_geom = QgsGeometry()
                    if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))

                # TODO: correctly handly different output geometry types (see todo above)
                if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(diff_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

        length = len(vlayerA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA) if len(featuresA) else 1
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = QgsGeometry(inFeatA.geometry())
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())
            lstIntersectingA = []

            for id in intersects:
                request = QgsFeatureRequest().setFilterFid(id)
                inFeatB = vlayerA.getFeatures(request).next()
                atMapB = inFeatB.attributes()
                tmpGeom = QgsGeometry(inFeatB.geometry())

                if geom.intersects(tmpGeom):
                    lstIntersectingA.append(tmpGeom)

            if len(lstIntersectingA) == 0:
                res_geom = geom
            else:
                intA = QgsGeometry.unaryUnion(lstIntersectingA)
                res_geom = geom.difference(intA)
                if res_geom is None:
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                           self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
                    res_geom = QgsGeometry()
                if res_geom.isGeosEmpty() or not res_geom.isGeosValid():
                    ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                           self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))

            # TODO: correctly handly different output geometry types (see todo above)

            try:
                outFeat.setGeometry(res_geom)
                outFeat.setAttributes(atMap)
                writer.addFeature(outFeat)
            except:
                ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                       self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            nElement += 1

        del writer
Ejemplo n.º 35
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Union.INPUT2))
        GEOS_EXCEPT = True
        FEATURE_EXCEPT = True
        vproviderA = vlayerA.dataProvider()

        fields = vector.combineVectorFields(vlayerA, vlayerB)
        names = [field.name() for field in fields]
        ProcessingLog.addToLog(ProcessingLog.LOG_INFO, str(names))
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(
            fields, vproviderA.geometryType(), vproviderA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    raise GeoAlgorithmExecutionException(
                        self.tr('Feature exception while computing union'))
            else:
                for id in intersects:
                    count += 1
                    request = QgsFeatureRequest().setFilterFid(id)
                    inFeatB = vlayerB.getFeatures(request).next()
                    atMapB = inFeatB.attributes()
                    tmpGeom = QgsGeometry(inFeatB.geometry())

                    if geom.intersects(tmpGeom):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if int_geom is None:
                            # There was a problem creating the intersection
                            raise GeoAlgorithmExecutionException(
                                self.tr('Geometry exception while computing '
                                        'intersection'))
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType() == 0:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                        try:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                        except Exception, err:
                            raise GeoAlgorithmExecutionException(
                                self.tr(
                                    'Feature exception while computing union'))

                try:
                    # the remaining bit of inFeatA's geometry
                    # if there is nothing left, this will just silently fail and we're good
                    diff_geom = QgsGeometry(geom)
                    if len(lstIntersectingB) != 0:
                        intB = QgsGeometry.unaryUnion(lstIntersectingB)
                        diff_geom = diff_geom.difference(intB)

                    if diff_geom.wkbType() == 0:
                        temp_list = diff_geom.asGeometryCollection()
                        for i in temp_list:
                            if i.type() == geom.type():
                                diff_geom = QgsGeometry(i)
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except Exception, err:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Feature exception while computing union'))
Ejemplo n.º 36
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(self.getParameterValue(self.JOIN))

        summary = self.getParameterValue(self.SUMMARY) == 1
        keep = self.getParameterValue(self.KEEP) == 1

        sumList = self.getParameterValue(self.STATS).lower().split(',')

        targetProvider = target.dataProvider()
        joinProvider = join.dataProvider()

        targetFields = targetProvider.fields()
        joinFields = joinProvider.fields()

        fieldList = QgsFields()

        if not summary:
            joinFields = vector.testForUniqueness(targetFields, joinFields)
            seq = range(0, len(targetFields) + len(joinFields))
            targetFields.extend(joinFields)
            targetFields = dict(zip(seq, targetFields))
        else:
            numFields = {}
            for j in xrange(len(joinFields)):
                if joinFields[j].type() in [QVariant.Int, QVariant.Double]:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + unicode(joinFields[j].name()),
                                         QVariant.Double, '', 24, 16)
                        fieldList.append(field)
            field = QgsField('count', QVariant.Double, '', 24, 16)
            fieldList.append(field)
            joinFields = vector.testForUniqueness(targetFields, fieldList)
            targetFields.extend(fieldList)
            seq = range(0, len(targetFields))
            targetFields = dict(zip(seq, targetFields))

        fields = QgsFields()
        for f in targetFields.values():
            fields.append(f)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, targetProvider.geometryType(), targetProvider.crs())

        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()

        index = vector.spatialindex(join)

        mapP2 = dict()
        features = vector.features(join)
        for f in features:
            mapP2[f.id()] = QgsFeature(f)

        features = vector.features(target)
        total = 100.0 / len(features)
        for c, f in enumerate(features):
            inGeom = f.geometry()
            atMap1 = f.attributes()
            outFeat.setGeometry(inGeom)
            none = True
            joinList = []
            if inGeom.type() == QGis.Point:
                joinList = index.intersects(inGeom.buffer(10, 2).boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            else:
                joinList = index.intersects(inGeom.boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1

            if check == 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]
                    if inGeom.intersects(inFeatB.geometry()):
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])

                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(
                                    sum(self._filterNull(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1 for _ in self._filterNull(
                                        numFields[j]))
                                    atMap.append(
                                        sum(self._filterNull(numFields[j])) /
                                        nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(
                                        min(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._median(numFields[j]))
                            else:
                                try:
                                    atMap.append(
                                        max(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())

            if keep:
                writer.addFeature(outFeat)
            else:
                if not none:
                    writer.addFeature(outFeat)

            progress.setPercentage(int(c * total))
        del writer
Ejemplo n.º 37
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)
        precision = self.getParameterValue(self.PRECISION)

        summary = self.getParameterValue(self.SUMMARY) == 1
        keep = self.getParameterValue(self.KEEP) == 1

        sumList = self.getParameterValue(self.STATS).lower().split(',')

        targetFields = target.fields()
        joinFields = join.fields()

        fieldList = QgsFields()

        if not summary:
            joinFields = vector.testForUniqueness(targetFields, joinFields)
            seq = list(range(len(targetFields) + len(joinFields)))
            targetFields.extend(joinFields)
            targetFields = dict(list(zip(seq, targetFields)))
        else:
            numFields = {}
            for j in range(len(joinFields)):
                if joinFields[j].type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + str(joinFields[j].name()), QVariant.Double, '', 24, 16)
                        fieldList.append(field)
            field = QgsField('count', QVariant.Double, '', 24, 16)
            fieldList.append(field)
            joinFields = vector.testForUniqueness(targetFields, fieldList)
            targetFields.extend(fieldList)
            seq = list(range(len(targetFields)))
            targetFields = dict(list(zip(seq, targetFields)))

        fields = QgsFields()
        for f in list(targetFields.values()):
            fields.append(f)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, target.wkbType(), target.crs())

        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()

        index = vector.spatialindex(join)

        mapP2 = dict()
        features = vector.features(join)
        for f in features:
            mapP2[f.id()] = QgsFeature(f)

        features = vector.features(target)
        total = 100.0 / len(features)
        for c, f in enumerate(features):
            atMap1 = f.attributes()
            outFeat.setGeometry(f.geometry())
            inGeom = vector.snapToPrecision(f.geometry(), precision)
            none = True
            joinList = []
            if inGeom.type() == QgsWkbTypes.PointGeometry:
                bbox = inGeom.buffer(10, 2).boundingBox()
            else:
                bbox = inGeom.boundingBox()
            bufferedBox = vector.bufferedBoundingBox(bbox, 0.51 * precision)
            joinList = index.intersects(bufferedBox)
            if len(joinList) > 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]
                    inGeomB = vector.snapToPrecision(inFeatB.geometry(), precision)

                    res = False
                    for predicate in predicates:
                        res = getattr(inGeom, predicate)(inGeomB)
                        if res:
                            break

                    if res:
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(list(zip(seq, atMap)))
                            break
                        else:
                            for j in list(numFields.keys()):
                                numFields[j].append(atMap2[j])

                if summary and not none:
                    atMap = atMap1
                    for j in list(numFields.keys()):
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(sum(self._filterNull(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1 for _ in self._filterNull(numFields[j]))
                                    atMap.append(sum(self._filterNull(numFields[j])) / nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(min(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._median(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(list(zip(seq, atMap)))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(list(atMap.values()))

            if keep:
                writer.addFeature(outFeat)
            else:
                if not none:
                    writer.addFeature(outFeat)

            progress.setPercentage(int(c * total))
        del writer
Ejemplo n.º 38
0
    def in_mask(self, feature, srid=None):
        if feature is None:  # expression overview
            return False

        if self.layer is None:
            return False

        try:
            # layer is not None but destroyed ?
            self.layer.id()
        except:
            self.reset_mask_layer()
            return False

        # mask layer empty due to unloaded memlayersaver plugin > no filtering
        if self.layer.featureCount() == 0:
            return True

        mask_geom, bbox = self.mask_geometry()
        geom = QgsGeometry(feature.geometry())
        if not geom.isGeosValid():
            geom = geom.buffer(0.0, 1)

        if geom is None:
            return False

        if srid is not None and self.layer.crs().postgisSrid() != srid:
            src_crs = QgsCoordinateReferenceSystem(srid)
            dest_crs = self.layer.crs()
            xform = QgsCoordinateTransform(src_crs, dest_crs,
                                           QgsProject.instance())
            try:
                geom.transform(xform)

            except Exception as e:
                for m in e.args:
                    QgsMessageLog.logMessage("in_mask - {}".format(m),
                                             "Extensions")
                    # transformation error. Check layer projection.
                    pass

        if geom.type() == QgsWkbTypes.PolygonGeometry:
            if (self.parameters.polygon_mask_method == 2
                    and not self.has_point_on_surface):
                self.parameters.polygon_mask_method = 1

            if self.parameters.polygon_mask_method == 0:
                # this method can only work when no geometry simplification is involved
                return mask_geom.overlaps(geom) or mask_geom.contains(geom)
            elif self.parameters.polygon_mask_method == 1:
                # the fastest method, but with possible inaccuracies
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(
                    geom.centroid())
            elif self.parameters.polygon_mask_method == 2:
                # will always work
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(
                    geom.pointOnSurface())
            else:
                return False
        elif geom.type() == QgsWkbTypes.LineGeometry:
            if self.parameters.line_mask_method == 0:
                return mask_geom.intersects(geom)
            elif self.parameters.line_mask_method == 1:
                return mask_geom.contains(geom)
            else:
                return False
        elif geom.type() == QgsWkbTypes.PointGeometry:
            return mask_geom.intersects(geom)
        else:
            return False