Example #1
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)
        precision = self.getParameterValue(self.PRECISION)

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

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

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

        fieldList = QgsFields()

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

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

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

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

        index = vector.spatialindex(join)

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

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

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

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

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

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

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

            progress.setPercentage(int(c * total))
        del writer
Example #2
0
    def processAlgorithm(self, feedback):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_A))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_B))
        fieldA = self.getParameterValue(self.FIELD_A)
        fieldB = self.getParameterValue(self.FIELD_B)

        idxA = layerA.fields().lookupField(fieldA)
        idxB = layerB.fields().lookupField(fieldB)

        if idxA != -1:
            fieldListA = QgsFields()
            fieldListA.append(layerA.fields()[idxA])
        else:
            fieldListA = layerA.fields()

        if idxB != -1:
            fieldListB = QgsFields()
            fieldListB.append(layerB.fields()[idxB])
        else:
            fieldListB = layerB.fields()

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        fieldListA.extend(fieldListB)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldListA, QgsWkbTypes.Point, layerA.crs())

        spatialIndex = vector.spatialindex(layerB)

        outFeat = QgsFeature()
        features = vector.features(layerA)
        total = 100.0 / len(features)
        hasIntersections = False

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()
            hasIntersections = False
            lines = spatialIndex.intersects(inGeom.boundingBox())

            engine = None
            if len(lines) > 0:
                hasIntersections = True
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
                engine.prepareGeometry()

            if hasIntersections:
                request = QgsFeatureRequest().setFilterFids(lines)
                for inFeatB in layerB.getFeatures(request):
                    tmpGeom = inFeatB.geometry()

                    points = []
                    attrsA = inFeatA.attributes()
                    if idxA != -1:
                        attrsA = [attrsA[idxA]]
                    attrsB = inFeatB.attributes()
                    if idxB != -1:
                        attrsB = [attrsB[idxB]]

                    if engine.intersects(tmpGeom.geometry()):
                        tempGeom = inGeom.intersection(tmpGeom)
                        if tempGeom.type() == QgsWkbTypes.PointGeometry:
                            if tempGeom.isMultipart():
                                points = tempGeom.asMultiPoint()
                            else:
                                points.append(tempGeom.asPoint())

                            for j in points:
                                outFeat.setGeometry(tempGeom.fromPoint(j))
                                attrsA.extend(attrsB)
                                outFeat.setAttributes(attrsA)
                                writer.addFeature(outFeat)

            feedback.setProgress(int(current * total))

        del writer
Example #3
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.INTERSECT, context)

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context)
        fieldsB = self.parameterAsFields(parameters, self.INTERSECT_FIELDS, context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fieldListA, QgsWkbTypes.Point, sourceA.sourceCrs())

        spatialIndex = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)

        outFeat = QgsFeature()
        features = sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a))
        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 0
        for current, inFeatA in enumerate(features):
            if feedback.isCanceled():
                break

            if not inFeatA.hasGeometry():
                continue

            inGeom = inFeatA.geometry()
            has_intersections = False
            lines = spatialIndex.intersects(inGeom.boundingBox())

            engine = None
            if len(lines) > 0:
                has_intersections = True
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
                engine.prepareGeometry()

            if has_intersections:
                request = QgsFeatureRequest().setFilterFids(lines)
                request.setDestinationCrs(sourceA.sourceCrs())
                request.setSubsetOfAttributes(field_indices_b)

                for inFeatB in sourceB.getFeatures(request):
                    if feedback.isCanceled():
                        break

                    tmpGeom = inFeatB.geometry()

                    points = []
                    if engine.intersects(tmpGeom.geometry()):
                        tempGeom = inGeom.intersection(tmpGeom)
                        out_attributes = [inFeatA.attributes()[i] for i in field_indices_a]
                        out_attributes.extend([inFeatB.attributes()[i] for i in field_indices_b])
                        if tempGeom.type() == QgsWkbTypes.PointGeometry:
                            if tempGeom.isMultipart():
                                points = tempGeom.asMultiPoint()
                            else:
                                points.append(tempGeom.asPoint())

                            for j in points:
                                outFeat.setGeometry(tempGeom.fromPoint(j))
                                outFeat.setAttributes(out_attributes)
                                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #4
0
    def processAlgorithm(self, feedback):
        layerA = dataobjects.getLayerFromString(self.getParameterValue(self.INPUT_A))
        layerB = dataobjects.getLayerFromString(self.getParameterValue(self.INPUT_B))
        fieldA = self.getParameterValue(self.FIELD_A)
        fieldB = self.getParameterValue(self.FIELD_B)

        idxA = layerA.fields().lookupField(fieldA)
        idxB = layerB.fields().lookupField(fieldB)

        if idxA != -1:
            fieldListA = QgsFields()
            fieldListA.append(layerA.fields()[idxA])
        else:
            fieldListA = layerA.fields()

        if idxB != -1:
            fieldListB = QgsFields()
            fieldListB.append(layerB.fields()[idxB])
        else:
            fieldListB = layerB.fields()

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        fieldListA.extend(fieldListB)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldListA,
                                                                     QgsWkbTypes.Point, layerA.crs())

        spatialIndex = vector.spatialindex(layerB)

        outFeat = QgsFeature()
        features = vector.features(layerA)
        total = 100.0 / len(features)
        hasIntersections = False

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()
            hasIntersections = False
            lines = spatialIndex.intersects(inGeom.boundingBox())

            engine = None
            if len(lines) > 0:
                hasIntersections = True
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
                engine.prepareGeometry()

            if hasIntersections:
                request = QgsFeatureRequest().setFilterFids(lines)
                for inFeatB in layerB.getFeatures(request):
                    tmpGeom = inFeatB.geometry()

                    points = []
                    attrsA = inFeatA.attributes()
                    if idxA != -1:
                        attrsA = [attrsA[idxA]]
                    attrsB = inFeatB.attributes()
                    if idxB != -1:
                        attrsB = [attrsB[idxB]]

                    if engine.intersects(tmpGeom.geometry()):
                        tempGeom = inGeom.intersection(tmpGeom)
                        if tempGeom.type() == QgsWkbTypes.PointGeometry:
                            if tempGeom.isMultipart():
                                points = tempGeom.asMultiPoint()
                            else:
                                points.append(tempGeom.asPoint())

                            for j in points:
                                outFeat.setGeometry(tempGeom.fromPoint(j))
                                attrsA.extend(attrsB)
                                outFeat.setAttributes(attrsA)
                                writer.addFeature(outFeat)

            feedback.setProgress(int(current * total))

        del writer
Example #5
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)
        precision = self.getParameterValue(self.PRECISION)

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

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

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

        fieldList = QgsFields()

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

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

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

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

        index = vector.spatialindex(join)

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

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

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

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

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

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

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

            progress.setPercentage(int(c * total))
        del writer
Example #6
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)

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

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS,
                                         context)
        fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS,
                                         context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fieldListA, geomType,
                                               sourceA.sourceCrs())

        outFeat = QgsFeature()
        indexB = QgsSpatialIndex(
            sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(sourceA.sourceCrs())), feedback)

        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
            if feedback.isCanceled():
                break

            if not featA.hasGeometry():
                continue

            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersects)
            request.setDestinationCrs(sourceA.sourceCrs())
            request.setSubsetOfAttributes(field_indices_b)

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

            for featB in sourceB.getFeatures(request):
                if feedback.isCanceled():
                    break

                tmpGeom = featB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    out_attributes = [
                        featA.attributes()[i] for i in field_indices_a
                    ]
                    out_attributes.extend(
                        [featB.attributes()[i] for i in field_indices_b])
                    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.isEmpty() or not int_geom.isGeosValid():
                        raise QgsProcessingException(
                            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)
                            outFeat.setAttributes(out_attributes)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        return {self.OUTPUT: dest_id}
Example #7
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)

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

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context)
        fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS, context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fieldListA, geomType, sourceA.sourceCrs())

        outFeat = QgsFeature()
        indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)

        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
            if feedback.isCanceled():
                break

            if not featA.hasGeometry():
                continue

            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersects)
            request.setDestinationCrs(sourceA.sourceCrs())
            request.setSubsetOfAttributes(field_indices_b)

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

            for featB in sourceB.getFeatures(request):
                if feedback.isCanceled():
                    break

                tmpGeom = featB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    out_attributes = [featA.attributes()[i] for i in field_indices_a]
                    out_attributes.extend([featB.attributes()[i] for i in field_indices_b])
                    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.isEmpty() or not int_geom.isGeosValid():
                        raise QgsProcessingException(
                            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)
                            outFeat.setAttributes(out_attributes)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        return {self.OUTPUT: dest_id}
Example #8
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(self.getParameterValue(self.JOIN))

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

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

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

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

        fieldList = QgsFields()

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

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

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

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

        index = vector.spatialindex(join)

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

        features = vector.features(target)

        count = 0
        total = 100.0 / len(features)

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

            if check == 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]  # cached feature from provider2
                    if inGeom.intersects(inFeatB.geometry()):
                        count += 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])
                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(
                                    sum(self._filter_null(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1
                                                   for _ in self._filter_null(
                                                       numFields[j]))
                                    atMap.append(
                                        sum(self._filter_null(numFields[j])) /
                                        nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(
                                        min(self._filter_null(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._myself(numFields[j]))
                            else:
                                try:
                                    atMap.append(
                                        max(self._filter_null(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))

            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())

            if keep:  # keep all records
                writer.addFeature(outFeat)
            else:  # keep only matching records
                if not none:
                    writer.addFeature(outFeat)

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

        del writer
Example #9
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)

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

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

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

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

        fieldList = QgsFields()

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

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

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

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

        index = vector.spatialindex(join)

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

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

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

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

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

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

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

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

            progress.setPercentage(int(c * total))
        del writer
Example #10
0
    def processAlgorithm(self, progress):
        progress.setText("Analysing inputs...")

        summary = self.getParameterValue(self.SUMMARY) == 1
        sumList = self.getParameterValue(self.STATS).upper().replace(" ", "").split(",")
        use_geom = self.getParameterValue(self.GEOMETRY)
        keep = self.getParameterValue(self.KEEP) == 1

        input1 = self.getParameterValue(self.INPUT1)
        layer1 = dataobjects.getObjectFromUri(input1)
        provider1 = layer1.dataProvider()
        fieldList1 = provider1.fields()

        input2 = self.getParameterValue(self.INPUT2)
        layer2 = dataobjects.getObjectFromUri(input2)
        provider2 = layer2.dataProvider()
        fieldList2 = provider2.fields()

        fieldList = QgsFields()
        if not summary:
            fieldList2 = vector.testForUniqueness(fieldList1, fieldList2)
            seq = range(0, len(fieldList1) + len(fieldList2))
            fieldList1.extend(fieldList2)
            fieldList1 = dict(zip(seq, fieldList1))
        else:
            numFields = {}
            for j in xrange(len(fieldList2)):
                if fieldList2[j].type() == QVariant.Int or fieldList2[j].type() == QVariant.Double:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(
                            i + unicode(fieldList2[j].name()), QVariant.Double, "real", 24, 16, "Summary field"
                        )
                        fieldList.append(field)
            field = QgsField("COUNT", QVariant.Double, "real", 24, 0, "Summary field")
            fieldList.append(field)
            fieldList2 = vector.testForUniqueness(fieldList1, fieldList)
            fieldList1.extend(fieldList)
            seq = range(0, len(fieldList1))
            fieldList1 = dict(zip(seq, fieldList1))

        progress.setPercentage(13)
        fields = QgsFields()
        for f in fieldList1.values():
            fields.append(f)
        output = self.getOutputFromName(self.OUTPUT)

        if use_geom == 0:
            # from target layer
            crs = provider1.crs()
            geometry_type = provider1.geometryType()
        else:
            # from joined layer
            crs = provider2.crs()
            if summary:
                geometry_type = self.singleToMultiGeom(provider2.geometryType())
            else:
                geometry_type = provider2.geometryType()

        writer = output.getVectorWriter(fields, geometry_type, crs)

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

        progress.setPercentage(15)
        start = 15.00
        add = 85.00 / provider1.featureCount()

        progress.setText("Creating spatial index...")
        index = vector.spatialindex(layer2)
        progress.setText("Processing spatial join...")
        fit1 = provider1.getFeatures()
        while fit1.nextFeature(inFeat):
            inGeom = inFeat.geometry()
            atMap1 = inFeat.attributes()
            if use_geom == 0:
                outFeat.setGeometry(inGeom)
            none = True
            joinList = []
            if inGeom.type() == QGis.Point:
                joinList = index.intersects(inGeom.buffer(10, 2).boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            else:
                joinList = index.intersects(inGeom.boundingBox())
                if len(joinList) > 0:
                    check = 0
                else:
                    check = 1
            if check == 0:
                count = 0
                multi_feature = []
                for i in joinList:
                    provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(i))).nextFeature(inFeatB)
                    if inGeom.intersects(inFeatB.geometry()):
                        count = count + 1
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            # first located feature
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            if use_geom == 1:
                                outFeat.setGeometry(inFeatB.geometry())
                            none = False
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])
                            if use_geom == 0:
                                if none:
                                    outFeat.setGeometry(inGeom)
                            else:
                                feature_list = self.extractAsMulti(inFeatB.geometry())
                                multi_feature.extend(feature_list)
                            none = False
                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == "SUM":
                                atMap.append(sum(numFields[j]))
                            elif k == "MEAN":
                                atMap.append(sum(numFields[j]) / count)
                            elif k == "MIN":
                                atMap.append(min(numFields[j]))
                            elif k == "MEDIAN":
                                atMap.append(myself(numFields[j]))
                            else:
                                atMap.append(max(numFields[j]))
                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
                    if use_geom == 1:
                        outGeom = QgsGeometry(self.convertGeometry(multi_feature, geometry_type))
                        outFeat.setGeometry(outGeom)
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())
            if keep:  # keep all records
                writer.addFeature(outFeat)
            else:  # keep only matching records
                if not none:
                    writer.addFeature(outFeat)
            start = start + add
            progress.setPercentage(start)

        del writer
Example #11
0
idxA = layerA.fieldNameIndex(fieldA)
idxB = layerB.fieldNameIndex(fieldB)

if allFieldsA:
    fieldListA = layerA.fields()
else:
    fieldListA = QgsFields()
    fieldListA.append(layerA.fields()[idxA])

if allFieldsB:
    fieldListB = layerB.fields()
else:
    fieldListB = QgsFields()
    fieldListB.append(layerB.fields()[idxB])

fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
fieldListA.extend(fieldListB)

writer = vector.VectorWriter(Intersections, None, fieldListA, QGis.WKBPoint,
                             layerA.dataProvider().crs())

spatialIndex = vector.spatialindex(layerB)

outFeat = QgsFeature()
features = vector.features(layerA)
total = 100.0 / len(features)
hasIntersections = False

for current, inFeatA in enumerate(features):
    inGeom = inFeatA.geometry()
    hasIntersections = False
Example #12
0
    def processAlgorithm(self, progress):
        progress.setText('Analysing inputs...')

        summary = self.getParameterValue(self.SUMMARY) == 1
        sumList = self.getParameterValue(self.STATS).upper().replace(
            ' ', '').split(',')
        use_geom = self.getParameterValue(self.GEOMETRY)
        keep = self.getParameterValue(self.KEEP) == 1

        input1 = self.getParameterValue(self.INPUT1)
        layer1 = dataobjects.getObjectFromUri(input1)
        provider1 = layer1.dataProvider()
        fieldList1 = provider1.fields()

        input2 = self.getParameterValue(self.INPUT2)
        layer2 = dataobjects.getObjectFromUri(input2)
        provider2 = layer2.dataProvider()
        fieldList2 = provider2.fields()

        fieldList = QgsFields()
        if not summary:
            fieldList2 = vector.testForUniqueness(fieldList1, fieldList2)
            seq = range(0, len(fieldList1) + len(fieldList2))
            fieldList1.extend(fieldList2)
            fieldList1 = dict(zip(seq, fieldList1))
        else:
            numFields = {}
            for j in xrange(len(fieldList2)):
                if fieldList2[j].type() == QVariant.Int or fieldList2[j].type(
                ) == QVariant.Double:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + unicode(fieldList2[j].name()),
                                         QVariant.Double, "real", 24, 16,
                                         "Summary field")
                        fieldList.append(field)
            field = QgsField("COUNT", QVariant.Double, "real", 24, 0,
                             "Summary field")
            fieldList.append(field)
            fieldList2 = vector.testForUniqueness(fieldList1, fieldList)
            fieldList1.extend(fieldList)
            seq = range(0, len(fieldList1))
            fieldList1 = dict(zip(seq, fieldList1))

        progress.setPercentage(13)
        fields = QgsFields()
        for f in fieldList1.values():
            fields.append(f)
        output = self.getOutputFromName(self.OUTPUT)

        if use_geom == 0:
            # from target layer
            crs = provider1.crs()
            geometry_type = provider1.geometryType()
        else:
            # from joined layer
            crs = provider2.crs()
            if summary:
                geometry_type = self.singleToMultiGeom(
                    provider2.geometryType())
            else:
                geometry_type = provider2.geometryType()

        writer = output.getVectorWriter(fields, geometry_type, crs)

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

        progress.setPercentage(15)
        start = 15.00
        add = 85.00 / provider1.featureCount()

        progress.setText('Creating spatial index...')
        index = vector.spatialindex(layer2)
        progress.setText('Processing spatial join...')
        fit1 = provider1.getFeatures()
        while fit1.nextFeature(inFeat):
            inGeom = inFeat.geometry()
            atMap1 = inFeat.attributes()
            if use_geom == 0:
                outFeat.setGeometry(inGeom)
            none = True
            joinList = []
            if inGeom.type() == QGis.Point:
                joinList = index.intersects(inGeom.buffer(10, 2).boundingBox())
                if len(joinList) > 0: check = 0
                else: check = 1
            else:
                joinList = index.intersects(inGeom.boundingBox())
                if len(joinList) > 0: check = 0
                else: check = 1
            if check == 0:
                count = 0
                multi_feature = []
                for i in joinList:
                    provider2.getFeatures(QgsFeatureRequest().setFilterFid(
                        int(i))).nextFeature(inFeatB)
                    if inGeom.intersects(inFeatB.geometry()):
                        count = count + 1
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            # first located feature
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            if use_geom == 1:
                                outFeat.setGeometry(inFeatB.geometry())
                            none = False
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])
                            if use_geom == 0:
                                if none:
                                    outFeat.setGeometry(inGeom)
                            else:
                                feature_list = self.extractAsMulti(
                                    inFeatB.geometry())
                                multi_feature.extend(feature_list)
                            none = False
                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == "SUM": atMap.append(sum(numFields[j]))
                            elif k == "MEAN":
                                atMap.append(sum(numFields[j]) / count)
                            elif k == "MIN":
                                atMap.append(min(numFields[j]))
                            elif k == "MEDIAN":
                                atMap.append(myself(numFields[j]))
                            else:
                                atMap.append(max(numFields[j]))
                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
                    if use_geom == 1:
                        outGeom = QgsGeometry(
                            self.convertGeometry(multi_feature, geometry_type))
                        outFeat.setGeometry(outGeom)
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())
            if keep:  # keep all records
                writer.addFeature(outFeat)
            else:  # keep only matching records
                if not none:
                    writer.addFeature(outFeat)
            start = start + add
            progress.setPercentage(start)

        del writer
Example #13
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))

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

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

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

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

        fieldList = QgsFields()

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

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

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

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

        index = vector.spatialindex(join)


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

        features = vector.features(target)

        count = 0
        total = 100.0 / len(features)

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

            if check == 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]  # cached feature from provider2
                    if inGeom.intersects(inFeatB.geometry()):
                        count += 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])
                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(sum(self._filter_null(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1 for _ in self._filter_null(numFields[j]))
                                    atMap.append(sum(self._filter_null(numFields[j])) / nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(min(self._filter_null(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._myself(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(self._filter_null(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))

            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())

            if keep: # keep all records
                writer.addFeature(outFeat)
            else: # keep only matching records
                if not none:
                    writer.addFeature(outFeat)

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

        del writer
Example #14
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.INTERSECT, context)

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context)
        fieldsB = self.parameterAsFields(parameters, self.INTERSECT_FIELDS, context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fieldListA, QgsWkbTypes.Point, sourceA.sourceCrs())

        spatialIndex = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)

        outFeat = QgsFeature()
        features = sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a))
        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 0
        for current, inFeatA in enumerate(features):
            if feedback.isCanceled():
                break

            if not inFeatA.hasGeometry():
                continue

            inGeom = inFeatA.geometry()
            has_intersections = False
            lines = spatialIndex.intersects(inGeom.boundingBox())

            engine = None
            if len(lines) > 0:
                has_intersections = True
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
                engine.prepareGeometry()

            if has_intersections:
                request = QgsFeatureRequest().setFilterFids(lines)
                request.setDestinationCrs(sourceA.sourceCrs())
                request.setSubsetOfAttributes(field_indices_b)

                for inFeatB in sourceB.getFeatures(request):
                    if feedback.isCanceled():
                        break

                    tmpGeom = inFeatB.geometry()

                    points = []
                    if engine.intersects(tmpGeom.geometry()):
                        tempGeom = inGeom.intersection(tmpGeom)
                        out_attributes = [inFeatA.attributes()[i] for i in field_indices_a]
                        out_attributes.extend([inFeatB.attributes()[i] for i in field_indices_b])
                        if tempGeom.type() == QgsWkbTypes.PointGeometry:
                            if tempGeom.isMultipart():
                                points = tempGeom.asMultiPoint()
                            else:
                                points.append(tempGeom.asPoint())

                            for j in points:
                                outFeat.setGeometry(tempGeom.fromPoint(j))
                                outFeat.setAttributes(out_attributes)
                                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}