Exemple #1
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(self.getParameterValue(Difference.INPUT))
        layerB = dataobjects.getObjectFromUri(self.getParameterValue(Difference.OVERLAY))
        ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID)

        geomType = layerA.dataProvider().geometryType()
        writer = self.getOutputFromName(Difference.OUTPUT).getVectorWriter(
            layerA.pendingFields(), geomType, layerA.dataProvider().crs()
        )

        outFeat = QgsFeature()
        index = vector.spatialindex(layerB)
        selectionA = vector.features(layerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            add = True
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())
            for i in intersections:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = layerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if diff_geom.intersects(tmpGeom):
                    diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    if diff_geom.isGeosEmpty():
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr("Feature with NULL geometry found."))
                    if not diff_geom.isGeosValid():
                        if ignoreInvalid:
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_ERROR,
                                self.tr("GEOS geoprocessing error: One or more input features have invalid geometry."),
                            )
                            add = False
                        else:
                            raise GeoAlgorithmExecutionException(
                                self.tr(
                                    'Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag'
                                )
                            )
                        break

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_WARNING,
                        self.tr("Feature geometry error: One or more output features ignored due to invalid geometry."),
                    )
                    continue

            progress.setPercentage(int(current * total))

        del writer
Exemple #2
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT2))

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
                                                                     geomType, vlayerA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('GEOS geoprocessing error: One or '
                                                       'more input features have invalid '
                                                       'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                               self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        continue

        del writer
Exemple #3
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.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(self.OUTPUT).getVectorWriter(fields,
                                                                     geomType, vproviderA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            for i in intersects:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = vlayerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if geom.intersects(tmpGeom):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_sym = geom.symDifference(tmpGeom)
                        int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('GEOS geoprocessing error: One or '
                                                       'more input features have invalid '
                                                       'geometry.'))
                        break
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                               self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        continue

        del writer
Exemple #4
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.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(self.OUTPUT).getVectorWriter(fields,
                                                                     geomType, vproviderA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = QgsGeometry(inFeatA.geometry())
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            for i in intersects:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = vlayerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if geom.intersects(tmpGeom):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_sym = geom.symDifference(tmpGeom)
                        int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('GEOS geoprocessing error: One or '
                                                       'more input features have invalid '
                                                       'geometry.'))
                        break
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                               self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        continue

        del writer
Exemple #5
0
    def check_geometry(self, vlayer):
        lstErrors = []
        if self.mySelection:
            layer = vlayer.selectedFeatures()
            nFeat = len(layer)
        else:
            layer = []
            ft = QgsFeature()
            fit = vlayer.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []))
            while fit.nextFeature(ft):
                layer.append(QgsFeature(ft))
            nFeat = len(layer)
        nElement = 0
        if nFeat > 0:
            self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
            self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat))
        for feat in layer:
            if not self.running:
                return list()
            geom = QgsGeometry(feat.geometry())  # ger reference to geometry
            self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement)
            nElement += 1
            # Check Add error
            if not geom.isGeosEmpty():
                lstErrors.append((feat.id(), list(geom.validateGeometry())))
        self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nFeat)

        if self.writeShape:
            fields = QgsFields()
            fields.append(QgsField("FEAT_ID", QVariant.Int))
            fields.append(QgsField("ERROR", QVariant.String))

            writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields,
                                         QGis.WKBPoint, vlayer.crs())
            for rec in lstErrors:
                if len(rec[1]) < 1:
                    continue
                for err in rec[1]:
                    fidItem = unicode(rec[0])
                    message = err.what()
                    if err.hasWhere():
                        locErr = err.where()
                        xP = locErr.x()
                        yP = locErr.y()
                        myPoint = QgsPoint(xP, yP)
                        geometry = QgsGeometry().fromPoint(myPoint)
                        ft = QgsFeature()
                        ft.setGeometry(geometry)
                        ft.setAttributes([fidItem, message])
                        writer.addFeature(ft)
            del writer
            return "writeShape"
        else:
            return lstErrors
Exemple #6
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.OVERLAY))
        ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID)

        geomType = QgsWkbTypes.multiType(layerA.wkbType())
        writer = self.getOutputFromName(
            Difference.OUTPUT).getVectorWriter(layerA.fields(),
                                               geomType,
                                               layerA.crs())

        outFeat = QgsFeature()
        index = vector.spatialindex(layerB)
        selectionA = vector.features(layerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            add = True
            geom = inFeatA.geometry()
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([])
            for inFeatB in layerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if diff_geom.intersects(tmpGeom):
                    diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    if diff_geom.isGeosEmpty():
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                               self.tr('Feature with NULL geometry found.'))
                    if not diff_geom.isGeosValid():
                        if ignoreInvalid:
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
                            add = False
                        else:
                            raise GeoAlgorithmExecutionException(self.tr('Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag'))
                        break

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                    continue

            progress.setPercentage(int(current * total))

        del writer
Exemple #7
0
    def check_geometry(self, vlayer):
        lstErrors = []
        if self.mySelection:
            layer = vlayer.selectedFeatures()
            nFeat = len(layer)
        else:
            layer = []
            ft = QgsFeature()
            fit = vlayer.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
            while fit.nextFeature(ft):
                layer.append(QgsFeature(ft))
            nFeat = len(layer)
        nElement = 0
        if nFeat > 0:
            self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
            self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat))
        for feat in layer:
            if not self.running:
                return list()
            geom = QgsGeometry(feat.geometry()) # ger reference to geometry
            self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement)
            nElement += 1
            # Check Add error
            if not geom.isGeosEmpty():
                lstErrors.append((feat.id(), list(geom.validateGeometry())))
        self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nFeat)

        if self.writeShape:
            fields = QgsFields()
            fields.append(QgsField("FEAT_ID", QVariant.Int))
            fields.append(QgsField("ERROR", QVariant.String))

            writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields,
                                         QGis.WKBPoint, vlayer.crs())
            for rec in lstErrors:
                if len(rec[1]) < 1:
                    continue
                for err in rec[1]:
                    fidItem = unicode(rec[0])
                    message = err.what()
                    if err.hasWhere():
                        locErr = err.where()
                        xP = locErr.x()
                        yP = locErr.y()
                        myPoint = QgsPoint(xP, yP)
                        geometry = QgsGeometry().fromPoint(myPoint)
                        ft = QgsFeature()
                        ft.setGeometry(geometry)
                        ft.setAttributes([fidItem, message])
                        writer.addFeature(ft)
            del writer
            return "writeShape"
        else:
            return lstErrors
Exemple #8
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.OVERLAY))

        geomType = layerA.dataProvider().geometryType()
        if geomType in GEOM_25D:
            raise GeoAlgorithmExecutionException(
                self.tr('Input layer does not support 2.5D type geometry ({}).').format(QgsWKBTypes.displayString(geomType)))

        writer = self.getOutputFromName(
            Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
                                               geomType,
                                               layerA.dataProvider().crs())

        outFeat = QgsFeature()
        index = vector.spatialindex(layerB)
        selectionA = vector.features(layerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            add = True
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())
            for i in intersections:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = layerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if diff_geom.intersects(tmpGeom):
                    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.'))
                        add = False
                        break

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                    continue

            progress.setPercentage(int(current * total))

        del writer
Exemple #9
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.OVERLAY))

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

        writer = self.getOutputFromName(
            Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
                                               geomType,
                                               layerA.dataProvider().crs())

        outFeat = QgsFeature()
        index = vector.spatialindex(layerB)
        selectionA = vector.features(layerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            add = True
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())
            for i in intersections:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = layerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if diff_geom.intersects(tmpGeom):
                    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.'))
                        add = False
                        break

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                    continue

            progress.setPercentage(int(current * total))

        del writer
Exemple #10
0
def dissolvePolygonsOnCanvas(writer, layer):
    """dissolve polygons of the layer and clip the dissolution with base extent"""
    settings = writer.settings
    baseExtent = settings.baseExtent
    baseExtentGeom = baseExtent.geometry()
    rotation = baseExtent.rotation()
    transform = QgsCoordinateTransform(layer.crs(), settings.crs)

    combi = None
    request = QgsFeatureRequest()
    request.setFilterRect(
        transform.transformBoundingBox(
            baseExtent.boundingBox(), QgsCoordinateTransform.ReverseTransform))
    for f in layer.getFeatures(request):
        geometry = f.geometry()
        if geometry is None:
            logMessage("null geometry skipped")
            continue

        # coordinate transformation - layer crs to project crs
        geom = QgsGeometry(geometry)
        if geom.transform(transform) != 0:
            logMessage("Failed to transform geometry")
            continue

        # check if geometry intersects with the base extent (rotated rect)
        if rotation and not baseExtentGeom.intersects(geom):
            continue

        if combi:
            combi = combi.combine(geom)
        else:
            combi = geom

    # clip geom with slightly smaller extent than base extent
    # to make sure that the clipped polygon stays within the base extent
    geom = combi.intersection(baseExtent.clone().scale(0.999999).geometry())
    if geom is None:
        return None

    # check if geometry is empty
    if geom.isGeosEmpty():
        logMessage("empty geometry")
        return None

    return geom
Exemple #11
0
def dissolvePolygonsOnCanvas(writer, layer):
  """dissolve polygons of the layer and clip the dissolution with base extent"""
  settings = writer.settings
  baseExtent = settings.baseExtent
  baseExtentGeom = baseExtent.geometry()
  rotation = baseExtent.rotation()
  transform = QgsCoordinateTransform(layer.crs(), settings.crs)

  combi = None
  request = QgsFeatureRequest()
  request.setFilterRect(transform.transformBoundingBox(baseExtent.boundingBox(), QgsCoordinateTransform.ReverseTransform))
  for f in layer.getFeatures(request):
    geometry = f.geometry()
    if geometry is None:
      logMessage("null geometry skipped")
      continue

    # coordinate transformation - layer crs to project crs
    geom = QgsGeometry(geometry)
    if geom.transform(transform) != 0:
      logMessage("Failed to transform geometry")
      continue

    # check if geometry intersects with the base extent (rotated rect)
    if rotation and not baseExtentGeom.intersects(geom):
      continue

    if combi:
      combi = combi.combine(geom)
    else:
      combi = geom

  # clip geom with slightly smaller extent than base extent
  # to make sure that the clipped polygon stays within the base extent
  geom = combi.intersection(baseExtent.clone().scale(0.999999).geometry())
  if geom is None:
    return None

  # check if geometry is empty
  if geom.isGeosEmpty():
    logMessage("empty geometry")
    return None

  return geom
Exemple #12
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.OVERLAY))

        GEOS_EXCEPT = True

        FEATURE_EXCEPT = True

        writer = self.getOutputFromName(Difference.OUTPUT).getVectorWriter(
            layerA.pendingFields(),
            layerA.dataProvider().geometryType(),
            layerA.dataProvider().crs())

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()

        index = vector.spatialindex(layerB)

        selectionA = vector.features(layerA)

        current = 0
        total = 100.0 / float(len(selectionA))

        for inFeatA in selectionA:
            add = True
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())
            for i in intersections:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = layerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                try:
                    if diff_geom.intersects(tmpGeom):
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    if diff_geom.isGeosEmpty():
                        GEOS_EXCEPT = False
                        add = False
                        break
                except:
                    GEOS_EXCEPT = False
                    add = False
                    break

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    FEATURE_EXCEPT = False
                    continue

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

        del writer

        if not GEOS_EXCEPT:
            ProcessingLog.addToLog(
                ProcessingLog.LOG_WARNING,
                self.tr('Geometry exception while computing difference'))
        if not FEATURE_EXCEPT:
            ProcessingLog.addToLog(
                ProcessingLog.LOG_WARNING,
                self.tr('Feature exception while computing difference'))
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT2))
        ignoreNull = self.getParameterValue(Intersection.IGNORE_NULL)

        geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(vlayerA.wkbType()))
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
                                                                     geomType, vlayerA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA) if len(selectionA) > 0 else 1
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = inFeatA.geometry()
            if not geom:
                if ignoreNull:
                    continue
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Input layer A contains NULL geometries. '
                                'Please check "Ignore NULL geometries" '
                                'if you want to run this algorithm anyway.'))
            if not geom.isGeosValid():
                raise GeoAlgorithmExecutionException(
                    self.tr('Input layer A contains invalid geometries '
                            '(feature {}). Unable to complete intersection '
                            'algorithm.'.format(inFeatA.id())))
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            for inFeatB in vlayerB.getFeatures(QgsFeatureRequest().setFilterFids(intersects)):
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if not geom:
                    if ignoreNull:
                        continue
                    else:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Input layer B contains NULL geometries. '
                                    'Please check "Ignore NULL geometries" '
                                    'if you want to run this algorithm anyway.'))
                if not geom.isGeosValid():
                    raise GeoAlgorithmExecutionException(
                        self.tr('Input layer B contains invalid geometries '
                                '(feature {}). Unable to complete intersection '
                                'algorithm.'.format(inFeatB.id())))

                if geom.intersects(tmpGeom):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com is not None:
                            int_sym = geom.symDifference(tmpGeom)
                            if int_sym:
                                diff_geom = int_com.difference(int_sym)
                                int_geom = QgsGeometry(diff_geom)

                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        raise GeoAlgorithmExecutionException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Feature geometry error: one or '
                                    'more output features ignored due '
                                    'to invalid geometry.'))

        del writer
Exemple #14
0
def union(union_a, union_b, callback=None):
    """Union of two vector 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/Union.py

    :param union_a: The vector layer for the union.
    :type union_a: QgsVectorLayer

    :param union_b: The vector layer for the union.
    :type union_b: 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 = union_steps['output_layer_name']
    processing_step = union_steps['step_name']
    output_layer_name = output_layer_name % (
        union_a.keywords['layer_purpose'],
        union_b.keywords['layer_purpose']
    )

    fields = union_a.fields()
    fields.extend(union_b.fields())

    writer = create_memory_layer(
        output_layer_name,
        union_a.geometryType(),
        union_a.crs(),
        fields
    )
    keywords_union_1 = union_a.keywords
    keywords_union_2 = union_b.keywords
    inasafe_fields_union_1 = keywords_union_1['inasafe_fields']
    inasafe_fields_union_2 = keywords_union_2['inasafe_fields']
    inasafe_fields = inasafe_fields_union_1
    inasafe_fields.update(inasafe_fields_union_2)

    # use to avoid modifying original source
    writer.keywords = dict(union_a.keywords)
    writer.keywords['inasafe_fields'] = inasafe_fields
    writer.keywords['title'] = output_layer_name
    writer.keywords['layer_purpose'] = 'aggregate_hazard'
    writer.keywords['hazard_keywords'] = keywords_union_1.copy()
    writer.keywords['aggregation_keywords'] = keywords_union_2.copy()
    skip_field = inasafe_fields_union_2[aggregation_id_field['key']]
    not_null_field_index = writer.fieldNameIndex(skip_field)

    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.

    index_a = create_spatial_index(union_b)
    index_b = create_spatial_index(union_a)

    count = 0
    n_element = 0
    # Todo fix callback
    # nFeat = len(union_a.getFeatures())
    for in_feat_a in union_a.getFeatures():
        # progress.setPercentage(nElement / float(nFeat) * 50)
        n_element += 1
        list_intersecting_b = []
        geom = geometry_checker(in_feat_a.geometry())
        at_map_a = in_feat_a.attributes()
        intersects = index_a.intersects(geom.boundingBox())
        if len(intersects) < 1:
            try:
                _write_feature(at_map_a, geom, writer, not_null_field_index)
            except:
                # This really shouldn't happen, as we haven't
                # edited the input geom at all
                LOGGER.debug(
                    tr('Feature geometry error: One or more output features '
                       'ignored due to invalid geometry.'))
        else:
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = QgsGeometry.createGeometryEngine(geom.geometry())
            engine.prepareGeometry()

            for in_feat_b in union_b.getFeatures(request):
                count += 1

                at_map_b = in_feat_b.attributes()
                tmp_geom = geometry_checker(in_feat_b.geometry())

                if engine.intersects(tmp_geom.geometry()):
                    int_geom = geometry_checker(geom.intersection(tmp_geom))
                    list_intersecting_b.append(QgsGeometry(tmp_geom))

                    if not int_geom:
                        # There was a problem creating the intersection
                        # LOGGER.debug(
                        #     tr('GEOS geoprocessing error: One or more input '
                        #        'features have invalid geometry.'))
                        pass
                        int_geom = QgsGeometry()
                    else:
                        int_geom = QgsGeometry(int_geom)

                    if int_geom.wkbType() == QgsWKBTypes.Unknown\
                            or QgsWKBTypes.flatType(
                            int_geom.geometry().wkbType()) == \
                                    QgsWKBTypes.GeometryCollection:
                        # Intersection produced different geometry types
                        temp_list = int_geom.asGeometryCollection()
                        for i in temp_list:
                            if i.type() == geom.type():
                                int_geom = QgsGeometry(geometry_checker(i))
                                try:
                                    _write_feature(
                                        at_map_a + at_map_b,
                                        int_geom,
                                        writer,
                                        not_null_field_index,
                                    )
                                except:
                                    LOGGER.debug(
                                        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 wkb_type_groups[
                            wkb_type_groups[int_geom.wkbType()]]:
                            try:
                                _write_feature(
                                    at_map_a + at_map_b,
                                    int_geom,
                                    writer,
                                    not_null_field_index)
                            except:
                                LOGGER.debug(
                                    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
            # are good
            diff_geom = QgsGeometry(geom)
            if len(list_intersecting_b) != 0:
                int_b = QgsGeometry.unaryUnion(list_intersecting_b)
                diff_geom = geometry_checker(diff_geom.difference(int_b))
                if diff_geom is None or \
                    diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                    # LOGGER.debug(
                    #     tr('GEOS geoprocessing error: One or more input '
                    #        'features have invalid geometry.'))
                    pass

            if diff_geom is not None and (
                            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(geometry_checker(i))
            try:
                _write_feature(
                    at_map_a,
                    diff_geom,
                    writer,
                    not_null_field_index)
            except:
                LOGGER.debug(
                    tr('Feature geometry error: One or more output features '
                       'ignored due to invalid geometry.'))

    length = len(union_a.fields())
    at_map_a = [None] * length

    # nFeat = len(union_b.getFeatures())
    for in_feat_a in union_b.getFeatures():
        # progress.setPercentage(nElement / float(nFeat) * 100)
        add = False
        geom = geometry_checker(in_feat_a.geometry())
        atMap = [None] * length
        atMap.extend(in_feat_a.attributes())
        intersects = index_b.intersects(geom.boundingBox())
        lstIntersectingA = []

        for id in intersects:
            request = QgsFeatureRequest().setFilterFid(id)
            inFeatB = union_a.getFeatures(request).next()
            atMapB = inFeatB.attributes()
            tmpGeom = QgsGeometry(geometry_checker(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:
                # LOGGER.debug(
                #    tr('GEOS geoprocessing error: One or more input features '
                #        'have null geometry.'))
                pass
                continue  # maybe it is better to fail like @gustry
                # does below ....
            if res_geom.isGeosEmpty() or not res_geom.isGeosValid():
                # LOGGER.debug(
                #    tr('GEOS geoprocessing error: One or more input features '
                #        'have invalid geometry.'))
                pass

        try:
            _write_feature(atMap, res_geom, writer, not_null_field_index)
        except:
            # LOGGER.debug(
            #     tr('Feature geometry error: One or more output features '
            #        'ignored due to invalid geometry.'))
            pass

        n_element += 1

    # End of copy/paste from processing

    writer.commitChanges()

    fill_hazard_class(writer)

    check_layer(writer)
    return writer
Exemple #15
0
def buffering(progress, writer, distance, field, useField, layer, dissolve,
              segments):

    if useField:
        field = layer.fieldNameIndex(field)

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

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

    # With dissolve
    if dissolve:
        first = True
        for inFeat in features:
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance

            inGeom = QgsGeometry(inFeat.geometry())
            if inGeom.isGeosEmpty() or not inGeom.isGeosValid():
                ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()))
                continue
            outGeom = inGeom.buffer(float(value), segments)
            if first:
                tempGeom = QgsGeometry(outGeom)
                first = False
            else:
                tempGeom = tempGeom.combine(outGeom)

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

        outFeat.setGeometry(tempGeom)
        outFeat.setAttributes(attrs)
        writer.addFeature(outFeat)
    else:
        # Without dissolve
        for inFeat in features:
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance
            inGeom = QgsGeometry(inFeat.geometry())
            if inGeom.isGeosEmpty() or not inGeom.isGeosValid():
                ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Feature {} has empty or invalid geometry. Skipping...'.format(inFeat.id()))
                continue

            outGeom = inGeom.buffer(float(value), segments)
            outFeat.setGeometry(outGeom)
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)
            current += 1
            progress.setPercentage(int(current * total))

    del writer
Exemple #16
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)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = 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:
                request = QgsFeatureRequest().setFilterFids(intersects)

                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerB.getFeatures(request):
                    count += 1

                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

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

                        if not int_geom:
                            # 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(
                        ) == QgsWkbTypes.Unknown 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(vlayerA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = 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:
                request = QgsFeatureRequest().setFilterFids(intersects)

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

                for inFeatB in vlayerA.getFeatures(request):
                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        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
Exemple #17
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Difference.OVERLAY))

        GEOS_EXCEPT = True

        FEATURE_EXCEPT = True

        writer = self.getOutputFromName(
            Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
                                               layerA.dataProvider().geometryType(),
                                               layerA.dataProvider().crs())

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()

        index = vector.spatialindex(layerB)

        selectionA = vector.features(layerA)

        current = 0
        total = 100.0 / float(len(selectionA))

        for inFeatA in selectionA:
            add = True
            geom = QgsGeometry(inFeatA.geometry())
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())
            for i in intersections:
                request = QgsFeatureRequest().setFilterFid(i)
                inFeatB = layerB.getFeatures(request).next()
                tmpGeom = QgsGeometry(inFeatB.geometry())
                try:
                    if diff_geom.intersects(tmpGeom):
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    if diff_geom.isGeosEmpty():
                        GEOS_EXCEPT = False
                        add = False
                        break
                except:
                    GEOS_EXCEPT = False
                    add = False
                    break

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    FEATURE_EXCEPT = False
                    continue

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

        del writer

        if not GEOS_EXCEPT:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                   self.tr('Geometry exception while computing difference'))
        if not FEATURE_EXCEPT:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                   self.tr('Feature exception while computing difference'))
Exemple #18
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(self.getParameterValue(Clip.INPUT))
        layerB = dataobjects.getObjectFromUri(self.getParameterValue(Clip.OVERLAY))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layerA.pendingFields(), layerA.dataProvider().geometryType(), layerA.dataProvider().crs()
        )

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()

        index = vector.spatialindex(layerB)

        selectionA = vector.features(layerA)

        total = 100.0 / len(selectionA)

        for current, inFeatA in enumerate(selectionA):
            geom = QgsGeometry(inFeatA.geometry())
            attrs = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            first = True
            found = False
            if len(intersects) > 0:
                for i in intersects:
                    layerB.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(inFeatB)
                    tmpGeom = QgsGeometry(inFeatB.geometry())
                    if tmpGeom.intersects(geom):
                        found = True
                        if first:
                            outFeat.setGeometry(QgsGeometry(tmpGeom))
                            first = False
                        else:
                            cur_geom = QgsGeometry(outFeat.geometry())
                            new_geom = QgsGeometry(cur_geom.combine(tmpGeom))
                            if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
                                ProcessingLog.addToLog(
                                    ProcessingLog.LOG_ERROR,
                                    self.tr(
                                        "GEOS geoprocessing error: One or "
                                        "more input features have invalid "
                                        "geometry."
                                    ),
                                )
                                break

                            outFeat.setGeometry(QgsGeometry(new_geom))
                if found:
                    cur_geom = QgsGeometry(outFeat.geometry())
                    new_geom = QgsGeometry(geom.intersection(cur_geom))
                    if (
                        new_geom.wkbType() == QGis.WKBUnknown
                        or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection
                    ):
                        int_com = QgsGeometry(geom.combine(cur_geom))
                        int_sym = QgsGeometry(geom.symDifference(cur_geom))
                        new_geom = QgsGeometry(int_com.difference(int_sym))
                        if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_ERROR,
                                self.tr(
                                    "GEOS geoprocessing error: One or more " "input features have invalid geometry."
                                ),
                            )
                            continue
                    try:
                        outFeat.setGeometry(new_geom)
                        outFeat.setAttributes(attrs)
                        writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr(
                                "Feature geometry error: One or more "
                                "output features ignored due to "
                                "invalid geometry."
                            ),
                        )
                        continue

            progress.setPercentage(int(current * total))

        del writer
Exemple #19
0
    def processAlgorithm(self, progress):
        useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
        field_names = self.getParameterValue(Dissolve.FIELD)
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Dissolve.INPUT))

        writer = self.getOutputFromName(Dissolve.OUTPUT).getVectorWriter(
            vlayerA.fields().toList(), vlayerA.wkbType(), vlayerA.crs())

        outFeat = QgsFeature()
        features = vector.features(vlayerA)
        total = 100.0 / len(features)

        if not useField:
            first = True
            # we dissolve geometries in blocks using unaryUnion
            geom_queue = []
            for current, inFeat in enumerate(features):
                progress.setPercentage(int(current * total))
                if first:
                    outFeat.setAttributes(inFeat.attributes())
                    first = False

                tmpInGeom = inFeat.geometry()
                if tmpInGeom.isEmpty() or tmpInGeom.isGeosEmpty():
                    continue

                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('ValidateGeometry()'
                                    'error: One or more '
                                    'input features have '
                                    'invalid geometry: ') + error.what())
                    continue

                geom_queue.append(tmpInGeom)

                if len(geom_queue) > 10000:
                    # queue too long, combine it
                    try:
                        temp_output_geometry = QgsGeometry.unaryUnion(
                            geom_queue)
                        geom_queue = [temp_output_geometry]
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while dissolving'))

            try:
                outFeat.setGeometry(QgsGeometry.unaryUnion(geom_queue))
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Geometry exception while dissolving'))

            writer.addFeature(outFeat)
        else:
            field_indexes = [
                vlayerA.fields().lookupField(f) for f in field_names.split(';')
            ]

            attribute_dict = {}
            geometry_dict = defaultdict(lambda: [])

            for inFeat in features:
                attrs = inFeat.attributes()

                index_attrs = tuple([attrs[i] for i in field_indexes])

                tmpInGeom = QgsGeometry(inFeat.geometry())
                if tmpInGeom.isGeosEmpty():
                    continue
                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('ValidateGeometry() '
                                    'error: One or more input'
                                    'features have invalid '
                                    'geometry: ') + error.what())

                if not index_attrs in attribute_dict:
                    # keep attributes of first feature
                    attribute_dict[index_attrs] = attrs

                geometry_dict[index_attrs].append(tmpInGeom)

            nFeat = len(attribute_dict)

            nElement = 0
            for key, value in list(geometry_dict.items()):
                outFeat = QgsFeature()
                nElement += 1
                progress.setPercentage(int(nElement * 100 / nFeat))
                try:
                    tmpOutGeom = QgsGeometry.unaryUnion(value)
                except:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Geometry exception while dissolving'))
                outFeat.setGeometry(tmpOutGeom)
                outFeat.setAttributes(attribute_dict[key])
                writer.addFeature(outFeat)

        del writer
Exemple #20
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.OVERLAY))

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

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layerA.pendingFields(),
            layerA.dataProvider().geometryType(),
            layerA.dataProvider().crs())

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()

        index = vector.spatialindex(layerB)

        selectionA = vector.features(layerA)

        total = 100.0 / len(selectionA)

        for current, inFeatA in enumerate(selectionA):
            geom = QgsGeometry(inFeatA.geometry())
            attrs = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            first = True
            found = False
            if len(intersects) > 0:
                for i in intersects:
                    layerB.getFeatures(QgsFeatureRequest().setFilterFid(
                        i)).nextFeature(inFeatB)
                    tmpGeom = QgsGeometry(inFeatB.geometry())
                    if tmpGeom.intersects(geom):
                        found = True
                        if first:
                            outFeat.setGeometry(QgsGeometry(tmpGeom))
                            first = False
                        else:
                            cur_geom = QgsGeometry(outFeat.geometry())
                            new_geom = QgsGeometry(cur_geom.combine(tmpGeom))
                            if new_geom.isGeosEmpty(
                            ) or not new_geom.isGeosValid():
                                ProcessingLog.addToLog(
                                    ProcessingLog.LOG_ERROR,
                                    self.tr('GEOS geoprocessing error: One or '
                                            'more input features have invalid '
                                            'geometry.'))
                                break

                            outFeat.setGeometry(QgsGeometry(new_geom))
                if found:
                    cur_geom = QgsGeometry(outFeat.geometry())
                    new_geom = QgsGeometry(geom.intersection(cur_geom))
                    if new_geom.wkbType(
                    ) == QGis.WKBUnknown or QgsWKBTypes.flatType(
                            new_geom.geometry().wkbType(
                            )) == QgsWKBTypes.GeometryCollection:
                        int_com = QgsGeometry(geom.combine(cur_geom))
                        int_sym = QgsGeometry(geom.symDifference(cur_geom))
                        new_geom = QgsGeometry(int_com.difference(int_sym))
                        if new_geom.isGeosEmpty(
                        ) or not new_geom.isGeosValid():
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_ERROR,
                                self.tr(
                                    'GEOS geoprocessing error: One or more '
                                    'input features have invalid geometry.'))
                            continue
                    try:
                        outFeat.setGeometry(new_geom)
                        outFeat.setAttributes(attrs)
                        writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to '
                                    'invalid geometry.'))
                        continue

            progress.setPercentage(int(current * total))

        del writer
def buffering(progress, writer, distance, field, useField, layer, dissolve,
              segments):

    if useField:
        field = layer.fieldNameIndex(field)

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

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

    # With dissolve
    if dissolve:
        first = True
        for inFeat in features:
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance

            inGeom = QgsGeometry(inFeat.geometry())
            if inGeom.isGeosEmpty():
                ProcessingLog.addToLog(
                    ProcessingLog.LOG_WARNING,
                    'Feature {} has empty geometry. Skipping...'.format(
                        inFeat.id()))
                continue
            if not inGeom.isGeosValid():
                ProcessingLog.addToLog(
                    ProcessingLog.LOG_WARNING,
                    'Feature {} has invalid geometry. Skipping...'.format(
                        inFeat.id()))
                continue
            outGeom = inGeom.buffer(float(value), segments)
            if first:
                tempGeom = QgsGeometry(outGeom)
                first = False
            else:
                tempGeom = tempGeom.combine(outGeom)

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

        outFeat.setGeometry(tempGeom)
        outFeat.setAttributes(attrs)
        writer.addFeature(outFeat)
    else:
        # Without dissolve
        for inFeat in features:
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance
            inGeom = QgsGeometry(inFeat.geometry())
            if inGeom.isGeosEmpty():
                ProcessingLog.addToLog(
                    ProcessingLog.LOG_WARNING,
                    'Feature {} has empty geometry. Skipping...'.format(
                        inFeat.id()))
                continue
            if not inGeom.isGeosValid():
                ProcessingLog.addToLog(
                    ProcessingLog.LOG_WARNING,
                    'Feature {} has invalid geometry. Skipping...'.format(
                        inFeat.id()))
                continue

            outGeom = inGeom.buffer(float(value), segments)
            outFeat.setGeometry(outGeom)
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)
            current += 1
            progress.setPercentage(int(current * total))

    del writer
Exemple #22
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
Exemple #23
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)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = 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:
                request = QgsFeatureRequest().setFilterFids(intersects)

                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerB.getFeatures(request):
                    count += 1

                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

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

                        if not int_geom:
                            # 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() == QgsWkbTypes.Unknown
                            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(vlayerA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = 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:
                request = QgsFeatureRequest().setFilterFids(intersects)

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

                for inFeatB in vlayerA.getFeatures(request):
                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        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
Exemple #24
0
    def processAlgorithm(self, progress):
        useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
        fieldname = self.getParameterValue(Dissolve.FIELD)
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Dissolve.INPUT))
        vproviderA = vlayerA.dataProvider()
        fields = vlayerA.fields()
        writer = self.getOutputFromName(
            Dissolve.OUTPUT).getVectorWriter(fields,
                                             vproviderA.geometryType(),
                                             vproviderA.crs())
        outFeat = QgsFeature()
        features = vector.features(vlayerA)
        total = 100.0 / len(features)

        if not useField:
            first = True
            for current, inFeat in enumerate(features):
                progress.setPercentage(int(current * total))
                if first:
                    attrs = inFeat.attributes()
                    tmpInGeom = QgsGeometry(inFeat.geometry())
                    if tmpInGeom.isGeosEmpty():
                        continue
                    errors = tmpInGeom.validateGeometry()
                    if len(errors) != 0:
                        for error in errors:
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('ValidateGeometry()'
                                                           'error: One or more '
                                                           'input features have '
                                                           'invalid geometry: ')
                                                   + error.what())
                        continue
                    outFeat.setGeometry(tmpInGeom)
                    first = False
                else:
                    tmpInGeom = QgsGeometry(inFeat.geometry())
                    if tmpInGeom.isGeosEmpty():
                        continue
                    tmpOutGeom = QgsGeometry(outFeat.geometry())
                    errors = tmpInGeom.validateGeometry()
                    if len(errors) != 0:
                        for error in errors:
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('ValidateGeometry()'
                                                           'error:One or more input'
                                                           'features have invalid '
                                                           'geometry: ')
                                                   + error.what())
                        continue
                    try:
                        tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom))
                        outFeat.setGeometry(tmpOutGeom)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while dissolving'))
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)
        else:
            fieldIdx = vlayerA.fieldNameIndex(fieldname)
            unique = vector.getUniqueValues(vlayerA, int(fieldIdx))
            nFeat = len(unique)
            myDict = {}
            attrDict = {}
            for item in unique:
                myDict[unicode(item).strip()] = []
                attrDict[unicode(item).strip()] = None

            unique = None

            for inFeat in features:
                attrs = inFeat.attributes()
                tempItem = attrs[fieldIdx]
                tmpInGeom = QgsGeometry(inFeat.geometry())
                if tmpInGeom.isGeosEmpty():
                    continue
                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('ValidateGeometry() '
                                                       'error: One or more input'
                                                       'features have invalid '
                                                       'geometry: ')
                                               + error.what())

                if attrDict[unicode(tempItem).strip()] is None:
                    # keep attributes of first feature
                    attrDict[unicode(tempItem).strip()] = attrs

                myDict[unicode(tempItem).strip()].append(tmpInGeom)

            features = None

            nElement = 0
            for key, value in myDict.items():
                nElement += 1
                progress.setPercentage(int(nElement * 100 / nFeat))
                try:
                    tmpOutGeom = QgsGeometry.unaryUnion(value)
                except:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Geometry exception while dissolving'))
                outFeat.setGeometry(tmpOutGeom)
                outFeat.setAttributes(attrDict[key])
                writer.addFeature(outFeat)

        del writer
Exemple #25
0
    def processAlgorithm(self, progress):
        useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
        fieldname = self.getParameterValue(Dissolve.FIELD)
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Dissolve.INPUT))
        vproviderA = vlayerA.dataProvider()
        fields = vlayerA.fields()
        writer = self.getOutputFromName(
            Dissolve.OUTPUT).getVectorWriter(fields,
                                             vproviderA.geometryType(),
                                             vproviderA.crs())
        outFeat = QgsFeature()
        features = vector.features(vlayerA)
        total = 100.0 / len(features)

        if not useField:
            first = True
            for current, inFeat in enumerate(features):
                progress.setPercentage(int(current * total))
                if first:
                    attrs = inFeat.attributes()
                    tmpInGeom = inFeat.geometry()
                    if tmpInGeom.isEmpty() or tmpInGeom.isGeosEmpty():
                        continue
                    errors = tmpInGeom.validateGeometry()
                    if len(errors) != 0:
                        for error in errors:
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('ValidateGeometry()'
                                                           'error: One or more '
                                                           'input features have '
                                                           'invalid geometry: ')
                                                   + error.what())
                        continue
                    outFeat.setGeometry(tmpInGeom)
                    first = False
                else:
                    tmpInGeom = inFeat.geometry()
                    if tmpInGeom.isEmpty() or tmpInGeom.isGeosEmpty():
                        continue
                    tmpOutGeom = outFeat.geometry()
                    errors = tmpInGeom.validateGeometry()
                    if len(errors) != 0:
                        for error in errors:
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('ValidateGeometry()'
                                                           'error:One or more input'
                                                           'features have invalid '
                                                           'geometry: ')
                                                   + error.what())
                        continue
                    try:
                        tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom))
                        outFeat.setGeometry(tmpOutGeom)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while dissolving'))
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)
        else:
            fieldIdx = vlayerA.fieldNameIndex(fieldname)
            unique = vector.getUniqueValues(vlayerA, int(fieldIdx))
            nFeat = len(unique)
            myDict = {}
            attrDict = {}
            for item in unique:
                myDict[unicode(item).strip()] = []
                attrDict[unicode(item).strip()] = None

            unique = None

            for inFeat in features:
                attrs = inFeat.attributes()
                tempItem = attrs[fieldIdx]
                tmpInGeom = QgsGeometry(inFeat.geometry())
                if tmpInGeom.isGeosEmpty():
                    continue
                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('ValidateGeometry() '
                                                       'error: One or more input'
                                                       'features have invalid '
                                                       'geometry: ')
                                               + error.what())

                if attrDict[unicode(tempItem).strip()] is None:
                    # keep attributes of first feature
                    attrDict[unicode(tempItem).strip()] = attrs

                myDict[unicode(tempItem).strip()].append(tmpInGeom)

            features = None

            nElement = 0
            for key, value in myDict.items():
                nElement += 1
                progress.setPercentage(int(nElement * 100 / nFeat))
                try:
                    tmpOutGeom = QgsGeometry.unaryUnion(value)
                except:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Geometry exception while dissolving'))
                outFeat.setGeometry(tmpOutGeom)
                outFeat.setAttributes(attrDict[key])
                writer.addFeature(outFeat)

        del writer
Exemple #26
0
def union(union_a, union_b, callback=None):
    """Union of two vector 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/Union.py

    :param union_a: The vector layer for the union.
    :type union_a: QgsVectorLayer

    :param union_b: The vector layer for the union.
    :type union_b: 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 = union_steps['output_layer_name']
    processing_step = union_steps['step_name']  # NOQA
    output_layer_name = output_layer_name % (
        union_a.keywords['layer_purpose'],
        union_b.keywords['layer_purpose']
    )

    fields = union_a.fields()
    fields.extend(union_b.fields())

    writer = create_memory_layer(
        output_layer_name,
        union_a.geometryType(),
        union_a.crs(),
        fields
    )
    keywords_union_1 = union_a.keywords
    keywords_union_2 = union_b.keywords
    inasafe_fields_union_1 = keywords_union_1['inasafe_fields']
    inasafe_fields_union_2 = keywords_union_2['inasafe_fields']
    inasafe_fields = inasafe_fields_union_1
    inasafe_fields.update(inasafe_fields_union_2)

    # use to avoid modifying original source
    writer.keywords = dict(union_a.keywords)
    writer.keywords['inasafe_fields'] = inasafe_fields
    writer.keywords['title'] = output_layer_name
    writer.keywords['layer_purpose'] = 'aggregate_hazard'
    writer.keywords['hazard_keywords'] = keywords_union_1.copy()
    writer.keywords['aggregation_keywords'] = keywords_union_2.copy()
    skip_field = inasafe_fields_union_2[aggregation_id_field['key']]
    not_null_field_index = writer.fieldNameIndex(skip_field)

    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.

    index_a = create_spatial_index(union_b)
    index_b = create_spatial_index(union_a)

    count = 0
    n_element = 0
    # Todo fix callback
    # nFeat = len(union_a.getFeatures())
    for in_feat_a in union_a.getFeatures():
        # progress.setPercentage(nElement / float(nFeat) * 50)
        n_element += 1
        list_intersecting_b = []
        geom = geometry_checker(in_feat_a.geometry())
        at_map_a = in_feat_a.attributes()
        intersects = index_a.intersects(geom.boundingBox())
        if len(intersects) < 1:
            try:
                _write_feature(at_map_a, geom, writer, not_null_field_index)
            except:
                # This really shouldn't happen, as we haven't
                # edited the input geom at all
                LOGGER.debug(
                    tr('Feature geometry error: One or more output features '
                       'ignored due to invalid geometry.'))
        else:
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = QgsGeometry.createGeometryEngine(geom.geometry())
            engine.prepareGeometry()

            for in_feat_b in union_b.getFeatures(request):
                count += 1

                at_map_b = in_feat_b.attributes()
                tmp_geom = geometry_checker(in_feat_b.geometry())

                if engine.intersects(tmp_geom.geometry()):
                    int_geom = geometry_checker(geom.intersection(tmp_geom))
                    list_intersecting_b.append(QgsGeometry(tmp_geom))

                    if not int_geom:
                        # There was a problem creating the intersection
                        # LOGGER.debug(
                        #     tr('GEOS geoprocessing error: One or more input '
                        #        'features have invalid geometry.'))
                        pass
                        int_geom = QgsGeometry()
                    else:
                        int_geom = QgsGeometry(int_geom)

                    if int_geom.wkbType() == QgsWKBTypes.Unknown\
                            or QgsWKBTypes.flatType(
                            int_geom.geometry().wkbType()) == \
                            QgsWKBTypes.GeometryCollection:
                        # Intersection produced different geometry types
                        temp_list = int_geom.asGeometryCollection()
                        for i in temp_list:
                            if i.type() == geom.type():
                                int_geom = QgsGeometry(geometry_checker(i))
                                try:
                                    _write_feature(
                                        at_map_a + at_map_b,
                                        int_geom,
                                        writer,
                                        not_null_field_index,
                                    )
                                except:
                                    LOGGER.debug(
                                        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 wkb_type_groups[
                                wkb_type_groups[int_geom.wkbType()]]:
                            try:
                                _write_feature(
                                    at_map_a + at_map_b,
                                    int_geom,
                                    writer,
                                    not_null_field_index)
                            except:
                                LOGGER.debug(
                                    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
            # are good
            diff_geom = QgsGeometry(geom)
            if len(list_intersecting_b) != 0:
                int_b = QgsGeometry.unaryUnion(list_intersecting_b)
                diff_geom = geometry_checker(diff_geom.difference(int_b))
                if diff_geom is None or \
                        diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                    # LOGGER.debug(
                    #     tr('GEOS geoprocessing error: One or more input '
                    #        'features have invalid geometry.'))
                    pass

            if diff_geom is not None and (
                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(geometry_checker(i))
            try:
                _write_feature(
                    at_map_a,
                    diff_geom,
                    writer,
                    not_null_field_index)
            except:
                LOGGER.debug(
                    tr('Feature geometry error: One or more output features '
                       'ignored due to invalid geometry.'))

    length = len(union_a.fields())

    # nFeat = len(union_b.getFeatures())
    for in_feat_a in union_b.getFeatures():
        # progress.setPercentage(nElement / float(nFeat) * 100)
        geom = geometry_checker(in_feat_a.geometry())
        atMap = [None] * length
        atMap.extend(in_feat_a.attributes())
        intersects = index_b.intersects(geom.boundingBox())
        lstIntersectingA = []

        for id in intersects:
            request = QgsFeatureRequest().setFilterFid(id)
            inFeatB = union_a.getFeatures(request).next()
            tmpGeom = QgsGeometry(geometry_checker(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:
                # LOGGER.debug(
                #    tr('GEOS geoprocessing error: One or more input features '
                #        'have null geometry.'))
                pass
                continue  # maybe it is better to fail like @gustry
                # does below ....
            if res_geom.isGeosEmpty() or not res_geom.isGeosValid():
                # LOGGER.debug(
                #    tr('GEOS geoprocessing error: One or more input features '
                #        'have invalid geometry.'))
                pass

        try:
            _write_feature(atMap, res_geom, writer, not_null_field_index)
        except:
            # LOGGER.debug(
            #     tr('Feature geometry error: One or more output features '
            #        'ignored due to invalid geometry.'))
            pass

        n_element += 1

    # End of copy/paste from processing

    writer.commitChanges()

    fill_hazard_class(writer)

    check_layer(writer)
    return writer
Exemple #27
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
Exemple #28
0
    def processAlgorithm(self, progress):
        useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
        field_names = self.getParameterValue(Dissolve.FIELD)
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Dissolve.INPUT))

        writer = self.getOutputFromName(
            Dissolve.OUTPUT).getVectorWriter(
                vlayerA.fields().toList(),
                vlayerA.wkbType(),
                vlayerA.crs())

        outFeat = QgsFeature()
        features = vector.features(vlayerA)
        total = 100.0 / len(features)

        if not useField:
            first = True
            # we dissolve geometries in blocks using unaryUnion
            geom_queue = []
            for current, inFeat in enumerate(features):
                progress.setPercentage(int(current * total))
                if first:
                    outFeat.setAttributes(inFeat.attributes())
                    first = False

                tmpInGeom = inFeat.geometry()
                if tmpInGeom.isEmpty() or tmpInGeom.isGeosEmpty():
                    continue

                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('ValidateGeometry()'
                                                       'error: One or more '
                                                       'input features have '
                                                       'invalid geometry: ')
                                               + error.what())
                    continue

                geom_queue.append(tmpInGeom)

                if len(geom_queue) > 10000:
                    # queue too long, combine it
                    try:
                        temp_output_geometry = QgsGeometry.unaryUnion(geom_queue)
                        geom_queue = [temp_output_geometry]
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while dissolving'))

            try:
                outFeat.setGeometry(QgsGeometry.unaryUnion(geom_queue))
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Geometry exception while dissolving'))

            writer.addFeature(outFeat)
        else:
            field_indexes = [vlayerA.fields().lookupField(f) for f in field_names.split(';')]

            attribute_dict = {}
            geometry_dict = defaultdict(lambda: [])

            for inFeat in features:
                attrs = inFeat.attributes()

                index_attrs = tuple([attrs[i] for i in field_indexes])

                tmpInGeom = QgsGeometry(inFeat.geometry())
                if tmpInGeom.isGeosEmpty():
                    continue
                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('ValidateGeometry() '
                                                       'error: One or more input'
                                                       'features have invalid '
                                                       'geometry: ')
                                               + error.what())

                if not index_attrs in attribute_dict:
                    # keep attributes of first feature
                    attribute_dict[index_attrs] = attrs

                geometry_dict[index_attrs].append(tmpInGeom)

            nFeat = len(attribute_dict)

            nElement = 0
            for key, value in list(geometry_dict.items()):
                outFeat = QgsFeature()
                nElement += 1
                progress.setPercentage(int(nElement * 100 / nFeat))
                try:
                    tmpOutGeom = QgsGeometry.unaryUnion(value)
                except:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Geometry exception while dissolving'))
                outFeat.setGeometry(tmpOutGeom)
                outFeat.setAttributes(attribute_dict[key])
                writer.addFeature(outFeat)

        del writer
Exemple #29
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT2))

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, vlayerA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            int_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[
                                int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_INFO,
                            self.
                            tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                               ))
                        continue

        del writer
Exemple #30
0
  def features(self, request=None, clipGeom=None):
    settings = self.writer.settings
    mapTo3d = settings.mapTo3d()
    baseExtent = settings.baseExtent
    baseExtentGeom = baseExtent.geometry()
    rotation = baseExtent.rotation()
    prop = self.prop

    useZ = prop.useZ()
    if useZ:
      srs_from = osr.SpatialReference()
      srs_from.ImportFromProj4(str(self.layer.crs().toProj4()))
      srs_to = osr.SpatialReference()
      srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4()))

      ogr_transform = osr.CreateCoordinateTransformation(srs_from, srs_to)
      clipGeomWkb = clipGeom.asWkb() if clipGeom else None
      ogr_clipGeom = ogr.CreateGeometryFromWkb(clipGeomWkb) if clipGeomWkb else None

    else:
      # z_func: function to get elevation at given point (x, y) on surface
      if prop.isHeightRelativeToDEM():
        if self.geomType == QGis.Polygon and prop.type_index == 1:  # Overlay
          z_func = lambda x, y: 0
        else:
          # get elevation from DEM
          z_func = lambda x, y: self.writer.demProvider.readValue(x, y)
      else:
        z_func = lambda x, y: 0

    request = request or QgsFeatureRequest()
    for f in self.layer.getFeatures(request):
      geometry = f.geometry()
      if geometry is None:
        logMessage("null geometry skipped")
        continue

      # coordinate transformation - layer crs to project crs
      geom = QgsGeometry(geometry)
      if geom.transform(self.transform) != 0:
        logMessage("Failed to transform geometry")
        continue

      # check if geometry intersects with the base extent (rotated rect)
      if rotation and not baseExtentGeom.intersects(geom):
        continue

      # create feature
      feat = Feature(self.writer, self, f)

      # transform_func: function to transform the map coordinates to 3d coordinates
      relativeHeight = prop.relativeHeight(f)

      def transform_func(x, y, z):
        return mapTo3d.transform(x, y, z + relativeHeight)

      if useZ:
        ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb())

        # transform geometry from layer CRS to project CRS
        if ogr_geom.Transform(ogr_transform) != 0:
          logMessage("Failed to transform geometry")
          continue

        # clip geometry
        if ogr_clipGeom and self.geomType == QGis.Line:
          ogr_geom = ogr_geom.Intersection(ogr_clipGeom)
          if ogr_geom is None:
            continue

        # check if geometry is empty
        if ogr_geom.IsEmpty():
          logMessage("empty geometry skipped")
          continue

        feat.geom = self.geomClass.fromOgrGeometry25D(ogr_geom, transform_func)

      else:
        # clip geometry
        if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]:
          geom = geom.intersection(clipGeom)
          if geom is None:
            continue

        # check if geometry is empty
        if geom.isGeosEmpty():
          logMessage("empty geometry skipped")
          continue

        if self.geomType == QGis.Polygon:
          feat.geom = self.geomClass.fromQgsGeometry(geom, z_func, transform_func, self.hasLabel())
          if prop.type_index == 1 and prop.isHeightRelativeToDEM():   # Overlay and relative to DEM
            feat.geom.splitPolygon(self.writer.triangleMesh())

        else:
          feat.geom = self.geomClass.fromQgsGeometry(geom, z_func, transform_func)

      if feat.geom is None:
        continue

      yield feat
Exemple #31
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.OVERLAY))

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

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layerA.pendingFields(),
            layerA.dataProvider().geometryType(),
            layerA.dataProvider().crs())

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()

        index = vector.spatialindex(layerB)

        selectionA = vector.features(layerA)

        current = 0
        total = 100.0 / float(len(selectionA))

        for inFeatA in selectionA:
            geom = QgsGeometry(inFeatA.geometry())
            attrs = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            first = True
            found = False
            if len(intersects) > 0:
                for i in intersects:
                    layerB.getFeatures(
                        QgsFeatureRequest().setFilterFid(i)).nextFeature(
                            inFeatB)
                    tmpGeom = QgsGeometry(inFeatB.geometry())
                    if tmpGeom.intersects(geom):
                        found = True
                        if first:
                            outFeat.setGeometry(QgsGeometry(tmpGeom))
                            first = False
                        else:
                            cur_geom = QgsGeometry(outFeat.geometry())
                            new_geom = QgsGeometry(cur_geom.combine(tmpGeom))
                            if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
                                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                       self.tr('GEOS geoprocessing error: One or '
                                                               'more input features have invalid '
                                                               'geometry.'))
                                break

                            outFeat.setGeometry(QgsGeometry(new_geom))
                if found:
                    cur_geom = QgsGeometry(outFeat.geometry())
                    new_geom = QgsGeometry(geom.intersection(cur_geom))
                    if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
                        int_com = QgsGeometry(geom.combine(cur_geom))
                        int_sym = QgsGeometry(geom.symDifference(cur_geom))
                        new_geom = QgsGeometry(int_com.difference(int_sym))
                        if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('GEOS geoprocessing error: One or more '
                                                           'input features have invalid geometry.'))
                            continue
                    try:
                        outFeat.setGeometry(new_geom)
                        outFeat.setAttributes(attrs)
                        writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('Feature geometry error: One or more '
                                                       'output features ignored due to '
                                                       'invalid geometry.'))
                        continue

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

        del writer
    def features(self, request=None, clipGeom=None):
        settings = self.writer.settings
        mapTo3d = settings.mapTo3d()
        baseExtent = settings.baseExtent
        baseExtentGeom = baseExtent.geometry()
        rotation = baseExtent.rotation()
        prop = self.prop

        useZ = prop.useZ()
        if useZ:
            srs_from = osr.SpatialReference()
            srs_from.ImportFromProj4(str(self.layer.crs().toProj4()))
            srs_to = osr.SpatialReference()
            srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4()))

            ogr_transform = osr.CreateCoordinateTransformation(
                srs_from, srs_to)
            clipGeomWkb = clipGeom.asWkb() if clipGeom else None
            ogr_clipGeom = ogr.CreateGeometryFromWkb(
                clipGeomWkb) if clipGeomWkb else None

        else:
            # z_func: function to get elevation at given point (x, y) on surface
            if prop.isHeightRelativeToDEM():
                if self.geomType == QGis.Polygon and prop.type_index == 1:  # Overlay
                    z_func = lambda x, y: 0
                else:
                    # get elevation from DEM
                    z_func = lambda x, y: self.writer.demProvider.readValue(
                        x, y)
            else:
                z_func = lambda x, y: 0

        request = request or QgsFeatureRequest()
        for f in self.layer.getFeatures(request):
            geometry = f.geometry()
            if geometry is None:
                logMessage("null geometry skipped")
                continue

            # coordinate transformation - layer crs to project crs
            geom = QgsGeometry(geometry)
            if geom.transform(self.transform) != 0:
                logMessage("Failed to transform geometry")
                continue

            # check if geometry intersects with the base extent (rotated rect)
            if rotation and not baseExtentGeom.intersects(geom):
                continue

            # create feature
            feat = Feature(self.writer, self, f)

            # transform_func: function to transform the map coordinates to 3d coordinates
            relativeHeight = prop.relativeHeight(f)

            def transform_func(x, y, z):
                return mapTo3d.transform(x, y, z + relativeHeight)

            if useZ:
                ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb())

                # transform geometry from layer CRS to project CRS
                if ogr_geom.Transform(ogr_transform) != 0:
                    logMessage("Failed to transform geometry")
                    continue

                # clip geometry
                if ogr_clipGeom and self.geomType == QGis.Line:
                    ogr_geom = ogr_geom.Intersection(ogr_clipGeom)
                    if ogr_geom is None:
                        continue

                # check if geometry is empty
                if ogr_geom.IsEmpty():
                    logMessage("empty geometry skipped")
                    continue

                feat.geom = self.geomClass.fromOgrGeometry25D(
                    ogr_geom, transform_func)

            else:
                # clip geometry
                if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]:
                    geom = geom.intersection(clipGeom)
                    if geom is None:
                        continue

                # check if geometry is empty
                if geom.isGeosEmpty():
                    logMessage("empty geometry skipped")
                    continue

                if self.geomType == QGis.Polygon:
                    feat.geom = self.geomClass.fromQgsGeometry(
                        geom, z_func, transform_func, self.hasLabel())
                    if prop.type_index == 1 and prop.isHeightRelativeToDEM(
                    ):  # Overlay and relative to DEM
                        feat.geom.splitPolygon(self.writer.triangleMesh())

                else:
                    feat.geom = self.geomClass.fromQgsGeometry(
                        geom, z_func, transform_func)

            if feat.geom is None:
                continue

            yield feat
Exemple #33
0
    def processAlgorithm(self, progress):
        useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
        fieldname = self.getParameterValue(Dissolve.FIELD)
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Dissolve.INPUT))
        vproviderA = vlayerA.dataProvider()
        fields = vlayerA.fields()
        writer = self.getOutputFromName(
            Dissolve.OUTPUT).getVectorWriter(fields,
                                             vproviderA.geometryType(),
                                             vproviderA.crs())
        outFeat = QgsFeature()
        nElement = 0
        features = vector.features(vlayerA)
        nFeat = len(features)

        if not useField:
            first = True
            for inFeat in features:
                nElement += 1
                progress.setPercentage(int(nElement * 100 / nFeat))
                if first:
                    attrs = inFeat.attributes()
                    tmpInGeom = QgsGeometry(inFeat.geometry())
                    if tmpInGeom.isGeosEmpty() or not tmpInGeom.isGeosValid():
                        continue
                    outFeat.setGeometry(tmpInGeom)
                    first = False
                else:
                    tmpInGeom = QgsGeometry(inFeat.geometry())
                    if tmpInGeom.isGeosEmpty() or not tmpInGeom.isGeosValid():
                        continue
                    tmpOutGeom = QgsGeometry(outFeat.geometry())
                    try:
                        tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom))
                        outFeat.setGeometry(tmpOutGeom)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while dissolving'))
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)
        else:
            fieldIdx = vlayerA.fieldNameIndex(fieldname)
            unique = vector.getUniqueValues(vlayerA, int(fieldIdx))
            nFeat = len(unique)
            myDict = {}
            attrDict = {}
            for item in unique:
                myDict[unicode(item).strip()] = []
                attrDict[unicode(item).strip()] = None

            unique = None

            for inFeat in features:
                attrs = inFeat.attributes()
                tempItem = attrs[fieldIdx]
                tmpInGeom = QgsGeometry(inFeat.geometry())
                if tmpInGeom.isGeosEmpty() or not tmpInGeom.isGeosValid():
                    continue

                if attrDict[unicode(tempItem).strip()] == None:
                    # keep attributes of first feature
                    attrDict[unicode(tempItem).strip()] = attrs

                myDict[unicode(tempItem).strip()].append(tmpInGeom)

            features = None

            for key, value in myDict.items():
                nElement += 1
                progress.setPercentage(int(nElement * 100 / nFeat))
                for i in range(len(value)):
                    tmpInGeom = value[i]

                    if i == 0:
                        tmpOutGeom = tmpInGeom
                    else:
                        try:
                            tmpOutGeom = QgsGeometry(
                                tmpOutGeom.combine(tmpInGeom))
                        except:
                            raise GeoAlgorithmExecutionException(
                                self.tr('Geometry exception while dissolving'))
                outFeat.setGeometry(tmpOutGeom)
                outFeat.setAttributes(attrDict[key])
                writer.addFeature(outFeat)

        del writer
Exemple #34
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT2))
        ignoreNull = self.getParameterValue(Intersection.IGNORE_NULL)

        geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(
            vlayerA.wkbType()))
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, vlayerA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = inFeatA.geometry()
            if not geom:
                if ignoreNull:
                    continue
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Input layer A contains NULL geometries. '
                                'Please check "Ignore NULL geometries" '
                                'if you want to run this algorithm anyway.'))
            if not geom.isGeosValid():
                raise GeoAlgorithmExecutionException(
                    self.tr('Input layer A contains invalid geometries '
                            '(feature {}). Unable to complete intersection '
                            'algorithm.'.format(inFeatA.id())))
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            for inFeatB in vlayerB.getFeatures(
                    QgsFeatureRequest().setFilterFids(intersects)):
                tmpGeom = QgsGeometry(inFeatB.geometry())
                if not geom:
                    if ignoreNull:
                        continue
                    else:
                        raise GeoAlgorithmExecutionException(
                            self.tr(
                                'Input layer B contains NULL geometries. '
                                'Please check "Ignore NULL geometries" '
                                'if you want to run this algorithm anyway.'))
                if not geom.isGeosValid():
                    raise GeoAlgorithmExecutionException(
                        self.tr(
                            'Input layer B contains invalid geometries '
                            '(feature {}). Unable to complete intersection '
                            'algorithm.'.format(inFeatB.id())))

                if geom.intersects(tmpGeom):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QGis.WKBUnknown or QgsWKBTypes.flatType(
                            int_geom.geometry().wkbType(
                            )) == QgsWKBTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com is not None:
                            int_sym = geom.symDifference(tmpGeom)
                            if int_sym:
                                diff_geom = int_com.difference(int_sym)
                                int_geom = QgsGeometry(diff_geom)

                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        raise GeoAlgorithmExecutionException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[
                                int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Feature geometry error: one or '
                                    'more output features ignored due '
                                    'to invalid geometry.'))

        del writer
Exemple #35
0
    def doCheck(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_LAYER))
        provider = layer.dataProvider()

        settings = QSettings()
        method = int(settings.value(settings_method_key, 1))

        valid_ouput = self.getOutputFromName(self.VALID_OUTPUT)
        valid_fields = layer.pendingFields().toList()
        valid_writer = valid_ouput.getVectorWriter(
            valid_fields,
            provider.geometryType(),
            layer.crs())
        valid_count = 0

        invalid_ouput = self.getOutputFromName(self.INVALID_OUTPUT)
        invalid_fields = layer.pendingFields().toList() + [
            QgsField(name='_errors',
                     type=QVariant.String,
                     len=255)]
        invalid_writer = invalid_ouput.getVectorWriter(
            invalid_fields,
            provider.geometryType(),
            layer.crs())
        invalid_count = 0

        error_ouput = self.getOutputFromName(self.ERROR_OUTPUT)
        error_fields = [
            QgsField(name='message',
                     type=QVariant.String,
                     len=255)]
        error_writer = error_ouput.getVectorWriter(
            error_fields,
            QGis.WKBPoint,
            layer.crs())
        error_count = 0

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, inFeat in enumerate(features):
            geom = QgsGeometry(inFeat.geometry())
            attrs = inFeat.attributes()

            valid = True
            if not geom.isGeosEmpty():
                errors = list(geom.validateGeometry())
                if errors:
                    # QGIS method return a summary at the end
                    if method == 1:
                        errors.pop()
                    valid = False
                    reasons = []
                    for error in errors:
                        errFeat = QgsFeature()
                        error_geom = QgsGeometry.fromPoint(error.where())
                        errFeat.setGeometry(error_geom)
                        errFeat.setAttributes([error.what()])
                        error_writer.addFeature(errFeat)
                        error_count += 1

                        reasons.append(error.what())

                    reason = "\n".join(reasons)
                    if len(reason) > 255:
                        reason = reason[:252] + '...'
                    attrs.append(reason)

            outFeat = QgsFeature()
            outFeat.setGeometry(geom)
            outFeat.setAttributes(attrs)

            if valid:
                valid_writer.addFeature(outFeat)
                valid_count += 1

            else:
                invalid_writer.addFeature(outFeat)
                invalid_count += 1

            progress.setPercentage(int(current * total))

        del valid_writer
        del invalid_writer
        del error_writer

        if valid_count == 0:
            valid_ouput.open = False
        if invalid_count == 0:
            invalid_ouput.open = False
        if error_count == 0:
            error_ouput.open = False
Exemple #36
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