Ejemplo n.º 1
0
 def testEquality(self):
     segment1 = QgsLineSegment2D(QgsPointXY(1, 2), QgsPointXY(3, 4))
     segment2 = QgsLineSegment2D(QgsPointXY(1, 2), QgsPointXY(3, 4))
     self.assertEqual(segment1, segment2)
     self.assertFalse(segment1 != segment2)
     segment2 = QgsLineSegment2D(QgsPointXY(1, 2), QgsPointXY(3, 5))
     self.assertNotEqual(segment1, segment2)
     self.assertTrue(segment1 != segment2)
     segment2 = QgsLineSegment2D(QgsPointXY(1, 2), QgsPointXY(5, 4))
     self.assertNotEqual(segment1, segment2)
     self.assertTrue(segment1 != segment2)
     segment2 = QgsLineSegment2D(QgsPointXY(1, 5), QgsPointXY(3, 4))
     self.assertNotEqual(segment1, segment2)
     self.assertTrue(segment1 != segment2)
     segment2 = QgsLineSegment2D(QgsPointXY(5, 2), QgsPointXY(3, 4))
     self.assertNotEqual(segment1, segment2)
     self.assertTrue(segment1 != segment2)
Ejemplo n.º 2
0
    def testChangeGeometry(self):
        # test changing geometries values from an edit buffer

        # make a layer with two features
        layer = createEmptyLayer()
        self.assertTrue(layer.startEditing())

        # add two features
        f1 = QgsFeature(layer.fields(), 1)
        f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
        f1.setAttributes(["test", 123])
        self.assertTrue(layer.addFeature(f1))

        f2 = QgsFeature(layer.fields(), 2)
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4)))
        f2.setAttributes(["test2", 246])
        self.assertTrue(layer.addFeature(f2))

        layer.commitChanges()
        layer.startEditing()

        self.assertEqual(layer.editBuffer().changedGeometries(), {})
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2))

        # change geometry
        layer.changeGeometry(1, QgsGeometry.fromPointXY(QgsPointXY(10, 20)))

        # test contents of buffer
        self.assertEqual(list(layer.editBuffer().changedGeometries().keys()),
                         [1])
        self.assertEqual(
            layer.editBuffer().changedGeometries()[1].constGet().x(), 10)
        self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2))
        self.assertEqual(layer.undoStack().count(), 1)

        self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 10)
        self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2)

        # apply second change to same feature
        layer.beginEditCommand(
            'second change'
        )  # need to use an edit command to avoid the two geometry changes being merged
        layer.changeGeometry(1, QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        layer.endEditCommand()

        # test contents of buffer
        self.assertEqual(list(layer.editBuffer().changedGeometries().keys()),
                         [1])
        self.assertEqual(
            layer.editBuffer().changedGeometries()[1].constGet().x(), 100)
        self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2))
        self.assertEqual(layer.undoStack().count(), 2)

        self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 100)
        self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2)

        layer.changeGeometry(2, QgsGeometry.fromPointXY(QgsPointXY(20, 40)))

        # test contents of buffer
        self.assertEqual(set(layer.editBuffer().changedGeometries().keys()),
                         set([1, 2]))
        self.assertEqual(
            layer.editBuffer().changedGeometries()[1].constGet().x(), 100)
        self.assertEqual(
            layer.editBuffer().changedGeometries()[2].constGet().x(), 20)
        self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(2))
        self.assertEqual(layer.undoStack().count(), 3)

        self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 100)
        self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 20)

        layer.undoStack().undo()

        self.assertEqual(list(layer.editBuffer().changedGeometries().keys()),
                         [1])
        self.assertEqual(
            layer.editBuffer().changedGeometries()[1].constGet().x(), 100)
        self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2))

        self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 100)
        self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2)

        layer.undoStack().undo()
        self.assertEqual(list(layer.editBuffer().changedGeometries().keys()),
                         [1])
        self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2))

        self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 10)
        self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2)

        layer.undoStack().undo()
        self.assertEqual(list(layer.editBuffer().changedGeometries().keys()),
                         [])
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(1))
        self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2))

        self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 1)
        self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2)
Ejemplo n.º 3
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE,
                                             context)

        expression = QgsExpression(
            self.parameterAsString(parameters, self.EXPRESSION, context))
        if expression.hasParserError():
            raise QgsProcessingException(expression.parserErrorString())

        expressionContext = self.createExpressionContext(
            parameters, context, source)
        expression.prepare(expressionContext)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink,
         dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                         fields, QgsWkbTypes.Point,
                                         source.sourceCrs(),
                                         QgsFeatureSink.RegeneratePrimaryKey)
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        current_progress = 0
        for current, f in enumerate(source.getFeatures()):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            current_progress = total * current
            feedback.setProgress(current_progress)

            expressionContext.setFeature(f)
            value = expression.evaluate(expressionContext)
            if expression.hasEvalError():
                feedback.pushInfo(
                    self.tr('Evaluation error for feature ID {}: {}').format(
                        f.id(), expression.evalErrorString()))
                continue

            fGeom = f.geometry()
            engine = QgsGeometry.createGeometryEngine(fGeom.constGet())
            engine.prepareGeometry()

            bbox = fGeom.boundingBox()
            if strategy == 0:
                pointCount = int(value)
            else:
                pointCount = int(round(value * da.measureArea(fGeom)))

            if pointCount == 0:
                feedback.pushInfo(
                    "Skip feature {} as number of points for it is 0.".format(
                        f.id()))
                continue

            index = QgsSpatialIndex()
            points = dict()

            nPoints = 0
            nIterations = 0
            maxIterations = pointCount * 200
            feature_total = total / pointCount if pointCount else 1

            random.seed()

            while nIterations < maxIterations and nPoints < pointCount:
                if feedback.isCanceled():
                    break

                rx = bbox.xMinimum() + bbox.width() * random.random()
                ry = bbox.yMinimum() + bbox.height() * random.random()

                p = QgsPointXY(rx, ry)
                geom = QgsGeometry.fromPointXY(p)
                if engine.contains(geom.constGet()) and \
                        vector.checkMinDistance(p, index, minDistance, points):
                    f = QgsFeature(nPoints)
                    f.initAttributes(1)
                    f.setFields(fields)
                    f.setAttribute('id', nPoints)
                    f.setGeometry(geom)
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    index.addFeature(f)
                    points[nPoints] = p
                    nPoints += 1
                    feedback.setProgress(current_progress +
                                         int(nPoints * feature_total))
                nIterations += 1

            if nPoints < pointCount:
                feedback.pushInfo(
                    self.tr('Could not generate requested number of random '
                            'points. Maximum number of attempts exceeded.'))

        feedback.setProgress(100)

        return {self.OUTPUT: dest_id}
Ejemplo n.º 4
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        endPoints = self.parameterAsSource(parameters, self.END_POINTS,
                                           context)
        if endPoints is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.END_POINTS))

        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters,
                                                    self.DIRECTION_FIELD,
                                                    context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD,
                                              context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD,
                                               context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH,
                                           context)
        defaultDirection = self.parameterAsEnum(parameters,
                                                self.DEFAULT_DIRECTION,
                                                context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD,
                                                context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED,
                                              context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = endPoints.fields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        feat = QgsFeature()
        feat.setFields(fields)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.LineString,
                                               network.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network, directionField,
                                          forwardValue, backwardValue,
                                          bothValue, defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance)

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathPointToLayer',
                                       'Loading end points…'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs(),
                                  context.transformContext())
        features = endPoints.getFeatures(request)
        total = 100.0 / endPoints.featureCount() if endPoints.featureCount(
        ) else 0

        points = [startPoint]
        source_attributes = {}
        i = 1
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            for p in f.geometry().vertices():
                points.append(QgsPointXY(p))
                source_attributes[i] = f.attributes()
                i += 1

            feedback.setProgress(int(current * total))

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathPointToLayer',
                                       'Building graph…'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathPointToLayer',
                                       'Calculating shortest paths…'))
        graph = builder.graph()

        idxStart = graph.findVertex(snappedPoints[0])
        tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

        nPoints = len(snappedPoints)
        total = 100.0 / nPoints if nPoints else 1
        for i in range(1, nPoints):
            if feedback.isCanceled():
                break

            idxEnd = graph.findVertex(snappedPoints[i])

            if tree[idxEnd] == -1:
                msg = self.tr(
                    'There is no route from start point ({}) to end point ({}).'
                    .format(startPoint.toString(), points[i].toString()))
                feedback.reportError(msg)
                # add feature with no geometry
                feat.clearGeometry()
                attrs = source_attributes[i]
                attrs.extend([NULL, points[i].toString()])
                feat.setAttributes(attrs)
                sink.addFeature(feat, QgsFeatureSink.FastInsert)
                continue

            route = [graph.vertex(idxEnd).point()]
            cost = costs[idxEnd]
            current = idxEnd
            while current != idxStart:
                current = graph.edge(tree[current]).fromVertex()
                route.append(graph.vertex(current).point())

            route.reverse()

            geom = QgsGeometry.fromPolylineXY(route)
            attrs = source_attributes[i]
            attrs.extend([
                startPoint.toString(), points[i].toString(), cost / multiplier
            ])
            feat.setAttributes(attrs)
            feat.setGeometry(geom)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 5
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context)
        order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context)
        text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context)

        group_field_index = source.fields().lookupField(group_field_name)
        order_field_index = source.fields().lookupField(order_field_name)

        if group_field_index >= 0:
            group_field_def = source.fields().at(group_field_index)
        else:
            group_field_def = None
        order_field_def = source.fields().at(order_field_index)

        fields = QgsFields()
        if group_field_def is not None:
            fields.append(group_field_def)
        begin_field = QgsField(order_field_def)
        begin_field.setName('begin')
        fields.append(begin_field)
        end_field = QgsField(order_field_def)
        end_field.setName('end')
        fields.append(end_field)

        output_wkb = QgsWkbTypes.LineString
        if QgsWkbTypes.hasM(source.wkbType()):
            output_wkb = QgsWkbTypes.addM(output_wkb)
        if QgsWkbTypes.hasZ(source.wkbType()):
            output_wkb = QgsWkbTypes.addZ(output_wkb)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, output_wkb, source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        points = dict()
        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([group_field_index, order_field_index]), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            point = f.geometry().constGet().clone()
            if group_field_index >= 0:
                group = f.attributes()[group_field_index]
            else:
                group = 1
            order = f.attributes()[order_field_index]
            if date_format != '':
                order = datetime.strptime(str(order), date_format)
            if group in points:
                points[group].append((order, point))
            else:
                points[group] = [(order, point)]

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        current = 0
        total = 100.0 / len(points) if points else 1
        for group, vertices in list(points.items()):
            if feedback.isCanceled():
                break

            vertices.sort(key=lambda x: (x[0] is None, x[0]))
            f = QgsFeature()
            attributes = []
            if group_field_index >= 0:
                attributes.append(group)
            attributes.extend([vertices[0][0], vertices[-1][0]])
            f.setAttributes(attributes)
            line = [node[1] for node in vertices]

            if text_dir:
                fileName = os.path.join(text_dir, '%s.txt' % group)

                with open(fileName, 'w') as fl:
                    fl.write('angle=Azimuth\n')
                    fl.write('heading=Coordinate_System\n')
                    fl.write('dist_units=Default\n')

                    for i in range(len(line)):
                        if i == 0:
                            fl.write('startAt=%f;%f;90\n' % (line[i].x(), line[i].y()))
                            fl.write('survey=Polygonal\n')
                            fl.write('[data]\n')
                        else:
                            angle = line[i - 1].azimuth(line[i])
                            distance = da.measureLine(QgsPointXY(line[i - 1]), QgsPointXY(line[i]))
                            fl.write('%f;%f;90\n' % (angle, distance))

            f.setGeometry(QgsGeometry(QgsLineString(line)))
            sink.addFeature(f, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 6
0
    def processAlgorithm(self, parameters, context, feedback):

        source = self.parameterAsSource(
            parameters,
            self.INPUT,
            context
        )

        sampled_raster = self.parameterAsRasterLayer(
            parameters,
            self.RASTERCOPY,
            context
        )

        columnPrefix = self.parameterAsString(
            parameters,
            self.COLUMN_PREFIX,
            context
        )

        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        source_fields = source.fields()
        raster_fields = QgsFields()

        # append field to vector as columnPrefix_bandCount
        for b in range(sampled_raster.bandCount()):
            raster_fields.append(QgsField(
                columnPrefix + str('_{}'.format(b + 1)), QVariant.Double
            )
            )

        # combine all the vector fields
        out_fields = QgsProcessingUtils.combineFields(source_fields, raster_fields)

        (sink, dest_id) = self.parameterAsSink(
            parameters,
            self.OUTPUT,
            context,
            out_fields,
            source.wkbType(),
            source.sourceCrs()
        )

        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        features = source.getFeatures()

        # create the coordinates transformation context
        ct = QgsCoordinateTransform(source.sourceCrs(), sampled_raster.crs(), context.transformContext())

        for n, i in enumerate(source.getFeatures()):

            attrs = i.attributes()

            if i.geometry().isMultipart() and i.geometry().constGet().partCount() > 1:
                sink.addFeature(i, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(n * total))
                feedback.reportError(self.tr('Impossible to sample data of multipart feature {}.').format(i.id()))
                continue

            # get the feature geometry as point
            point = QgsPointXY()
            if i.geometry().isMultipart():
                point = i.geometry().asMultiPoint()[0]
            else:
                point = i.geometry().asPoint()

            # reproject to raster crs
            try:
                point = ct.transform(point)
            except QgsCsException:
                for b in range(sampled_raster.bandCount()):
                    attrs.append(None)
                i.setAttributes(attrs)
                sink.addFeature(i, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(n * total))
                feedback.reportError(self.tr('Could not reproject feature {} to raster CRS').format(i.id()))
                continue

            for b in range(sampled_raster.bandCount()):
                value, ok = sampled_raster.dataProvider().sample(point, b + 1)
                if ok:
                    attrs.append(value)
                else:
                    attrs.append(NULL)

            i.setAttributes(attrs)

            sink.addFeature(i, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(n * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 7
0
    def ovals(self, sink, source, width, height, rotation, segments, feedback):
        features = source.getFeatures()
        ft = QgsFeature()

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        if rotation >= 0:
            for current, feat in enumerate(features):
                if feedback.isCanceled():
                    break

                if not feat.hasGeometry():
                    continue

                w = feat[width]
                h = feat[height]
                angle = feat[rotation]
                if not w or not h or not angle:
                    feedback.pushInfo(
                        self.tr('Feature {} has empty '
                                'width, height or angle. '
                                'Skipping...'.format(feat.id())))
                    continue

                xOffset = w / 2.0
                yOffset = h / 2.0
                phi = angle * math.pi / 180

                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = []
                for t in [(2 * math.pi) / segments * i
                          for i in range(segments)]:
                    points.append(
                        (xOffset * math.cos(t), yOffset * math.sin(t)))
                polygon = [[
                    QgsPointXY(
                        i[0] * math.cos(phi) + i[1] * math.sin(phi) + x,
                        -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y)
                    for i in points
                ]]

                ft.setGeometry(QgsGeometry.fromPolygonXY(polygon))
                ft.setAttributes(feat.attributes())
                sink.addFeature(ft, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))
        else:
            for current, feat in enumerate(features):
                if feedback.isCanceled():
                    break

                if not feat.hasGeometry():
                    continue

                w = feat[width]
                h = feat[height]
                if not w or not h:
                    feedback.pushInfo(
                        self.tr('Feature {} has empty '
                                'width or height. '
                                'Skipping...'.format(feat.id())))
                    continue

                xOffset = w / 2.0
                yOffset = h / 2.0

                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = []
                for t in [(2 * math.pi) / segments * i
                          for i in range(segments)]:
                    points.append(
                        (xOffset * math.cos(t), yOffset * math.sin(t)))
                polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygonXY(polygon))
                ft.setAttributes(feat.attributes())
                sink.addFeature(ft, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))
Ejemplo n.º 8
0
def UpdateBeamsData(packet, cornerPointUL, cornerPointUR, cornerPointLR,
                    cornerPointLL):
    ''' Update Beams Values '''
    lat = packet.GetSensorLatitude()
    lon = packet.GetSensorLongitude()
    alt = packet.GetSensorTrueAltitude()

    beamsLyr = qgsu.selectLayerByName(Beams_lyr)

    try:
        if beamsLyr is not None:
            beamsLyr.startEditing()
            if beamsLyr.featureCount() == 0:

                # UL
                featureUL = QgsFeature()
                featureUL.setAttributes(
                    [lon, lat, alt, cornerPointUL[1], cornerPointUL[0]])
                surface = QgsGeometry.fromPolylineXY([
                    QgsPointXY(lon, lat),
                    QgsPointXY(cornerPointUL[1], cornerPointUL[0])
                ])
                featureUL.setGeometry(surface)
                beamsLyr.addFeatures([featureUL])
                # UR
                featureUR = QgsFeature()
                featureUR.setAttributes(
                    [lon, lat, alt, cornerPointUR[1], cornerPointUR[0]])
                surface = QgsGeometry.fromPolylineXY([
                    QgsPointXY(lon, lat),
                    QgsPointXY(cornerPointUR[1], cornerPointUR[0])
                ])
                featureUR.setGeometry(surface)
                beamsLyr.addFeatures([featureUR])
                # LR
                featureLR = QgsFeature()
                featureLR.setAttributes(
                    [lon, lat, alt, cornerPointLR[1], cornerPointLR[0]])
                surface = QgsGeometry.fromPolylineXY([
                    QgsPointXY(lon, lat),
                    QgsPointXY(cornerPointLR[1], cornerPointLR[0])
                ])
                featureLR.setGeometry(surface)
                beamsLyr.addFeatures([featureLR])
                # LL
                featureLL = QgsFeature()
                featureLL.setAttributes(
                    [lon, lat, alt, cornerPointLL[1], cornerPointLL[0]])
                surface = QgsGeometry.fromPolylineXY([
                    QgsPointXY(lon, lat),
                    QgsPointXY(cornerPointLL[1], cornerPointLL[0])
                ])
                featureLL.setGeometry(surface)
                beamsLyr.addFeatures([featureLL])

            else:
                beamsLyr.beginEditCommand("ChangeGeometry + ChangeAttribute")
                # UL
                fetId = 1
                attrib = {
                    0: lon,
                    1: lat,
                    2: alt,
                    3: cornerPointUL[1],
                    4: cornerPointUL[0]
                }
                beamsLyr.dataProvider().changeAttributeValues({fetId: attrib})
                beamsLyr.dataProvider().changeGeometryValues({
                    fetId:
                    QgsGeometry.fromPolylineXY([
                        QgsPointXY(lon, lat),
                        QgsPointXY(cornerPointUL[1], cornerPointUL[0])
                    ])
                })
                # UR
                fetId = 2
                attrib = {
                    0: lon,
                    1: lat,
                    2: alt,
                    3: cornerPointUR[1],
                    4: cornerPointUR[0]
                }
                beamsLyr.dataProvider().changeAttributeValues({fetId: attrib})
                beamsLyr.dataProvider().changeGeometryValues({
                    fetId:
                    QgsGeometry.fromPolylineXY([
                        QgsPointXY(lon, lat),
                        QgsPointXY(cornerPointUR[1], cornerPointUR[0])
                    ])
                })
                # LR
                fetId = 3
                attrib = {
                    0: lon,
                    1: lat,
                    2: alt,
                    3: cornerPointLR[1],
                    4: cornerPointLR[0]
                }
                beamsLyr.dataProvider().changeAttributeValues({fetId: attrib})
                beamsLyr.dataProvider().changeGeometryValues({
                    fetId:
                    QgsGeometry.fromPolylineXY([
                        QgsPointXY(lon, lat),
                        QgsPointXY(cornerPointLR[1], cornerPointLR[0])
                    ])
                })
                # LL
                fetId = 4
                attrib = {
                    0: lon,
                    1: lat,
                    2: alt,
                    3: cornerPointLL[1],
                    4: cornerPointLL[0]
                }
                beamsLyr.dataProvider().changeAttributeValues({fetId: attrib})
                beamsLyr.dataProvider().changeGeometryValues({
                    fetId:
                    QgsGeometry.fromPolylineXY([
                        QgsPointXY(lon, lat),
                        QgsPointXY(cornerPointLL[1], cornerPointLL[0])
                    ])
                })

                beamsLyr.endEditCommand()

            CommonLayer(beamsLyr)

    except Exception as e:
        qgsu.showUserAndLogMessage(
            QCoreApplication.translate("QgsFmvUtils",
                                       "Failed Update Beams Layer! : "),
            str(e))
    return
Ejemplo n.º 9
0
def UpdateFootPrintData(cornerPointUL, cornerPointUR, cornerPointLR,
                        cornerPointLL):
    ''' Update Footprint Values '''
    footprintLyr = qgsu.selectLayerByName(Footprint_lyr)

    try:
        if footprintLyr is not None:
            footprintLyr.startEditing()
            if footprintLyr.featureCount() == 0:
                feature = QgsFeature()
                feature.setAttributes([
                    cornerPointUL[1], cornerPointUL[0], cornerPointUR[1],
                    cornerPointUR[0], cornerPointLR[1], cornerPointLR[0],
                    cornerPointLL[1], cornerPointLL[0]
                ])
                surface = QgsGeometry.fromPolygonXY([[
                    QgsPointXY(cornerPointUL[1], cornerPointUL[0]),
                    QgsPointXY(cornerPointUR[1], cornerPointUR[0]),
                    QgsPointXY(cornerPointLR[1], cornerPointLR[0]),
                    QgsPointXY(cornerPointLL[1], cornerPointLL[0]),
                    QgsPointXY(cornerPointUL[1], cornerPointUL[0])
                ]])
                feature.setGeometry(surface)
                footprintLyr.addFeatures([feature])
            else:
                footprintLyr.beginEditCommand(
                    "ChangeGeometry + ChangeAttribute")
                fetId = 1
                attrib = {
                    0: cornerPointUL[1],
                    1: cornerPointUL[0],
                    2: cornerPointUR[1],
                    3: cornerPointUR[0],
                    4: cornerPointLR[1],
                    5: cornerPointLR[0],
                    6: cornerPointLL[1],
                    7: cornerPointLL[0]
                }

                footprintLyr.dataProvider().changeAttributeValues(
                    {fetId: attrib})

                footprintLyr.dataProvider().changeGeometryValues({
                    fetId:
                    QgsGeometry.fromPolygonXY([[
                        QgsPointXY(cornerPointUL[1], cornerPointUL[0]),
                        QgsPointXY(cornerPointUR[1], cornerPointUR[0]),
                        QgsPointXY(cornerPointLR[1], cornerPointLR[0]),
                        QgsPointXY(cornerPointLL[1], cornerPointLL[0]),
                        QgsPointXY(cornerPointUL[1], cornerPointUL[0])
                    ]])
                })
            footprintLyr.endEditCommand()

            CommonLayer(footprintLyr)

    except Exception as e:
        qgsu.showUserAndLogMessage(
            QCoreApplication.translate("QgsFmvUtils",
                                       "Failed Update FootPrint Layer! : "),
            str(e))
    return
Ejemplo n.º 10
0
    def clip_voronoi(self, edges, c, width, height, extent, exX, exY):
        """Clip voronoi function based on code written for Inkscape.
        Copyright (C) 2010 Alvin Penner, [email protected]
        """
        def clip_line(x1, y1, x2, y2, w, h, x, y):
            if x1 < 0 - x and x2 < 0 - x:
                return [0, 0, 0, 0]
            if x1 > w + x and x2 > w + x:
                return [0, 0, 0, 0]
            if x1 < 0 - x:
                y1 = (y1 * x2 - y2 * x1) / (x2 - x1)
                x1 = 0 - x
            if x2 < 0 - x:
                y2 = (y1 * x2 - y2 * x1) / (x2 - x1)
                x2 = 0 - x
            if x1 > w + x:
                y1 = y1 + (w + x - x1) * (y2 - y1) / (x2 - x1)
                x1 = w + x
            if x2 > w + x:
                y2 = y1 + (w + x - x1) * (y2 - y1) / (x2 - x1)
                x2 = w + x
            if y1 < 0 - y and y2 < 0 - y:
                return [0, 0, 0, 0]
            if y1 > h + y and y2 > h + y:
                return [0, 0, 0, 0]
            if x1 == x2 and y1 == y2:
                return [0, 0, 0, 0]
            if y1 < 0 - y:
                x1 = (x1 * y2 - x2 * y1) / (y2 - y1)
                y1 = 0 - y
            if y2 < 0 - y:
                x2 = (x1 * y2 - x2 * y1) / (y2 - y1)
                y2 = 0 - y
            if y1 > h + y:
                x1 = x1 + (h + y - y1) * (x2 - x1) / (y2 - y1)
                y1 = h + y
            if y2 > h + y:
                x2 = x1 + (h + y - y1) * (x2 - x1) / (y2 - y1)
                y2 = h + y
            return [x1, y1, x2, y2]

        lines = []
        hasXMin = False
        hasYMin = False
        hasXMax = False
        hasYMax = False
        for edge in edges:
            if edge[1] >= 0 and edge[2] >= 0:
                # Two vertices
                [x1, y1, x2, y2] = clip_line(
                    c.vertices[edge[1]][0],
                    c.vertices[edge[1]][1],
                    c.vertices[edge[2]][0],
                    c.vertices[edge[2]][1],
                    width,
                    height,
                    exX,
                    exY,
                )
            elif edge[1] >= 0:
                # Only one vertex
                if c.lines[edge[0]][1] == 0:
                    # Vertical line
                    xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0]
                    if c.vertices[edge[1]][1] > (height + exY) / 2:
                        ytemp = height + exY
                    else:
                        ytemp = 0 - exX
                else:
                    xtemp = width + exX
                    ytemp = (c.lines[edge[0]][2] - (width + exX) *
                             c.lines[edge[0]][0]) / c.lines[edge[0]][1]
                [x1, y1, x2, y2] = clip_line(
                    c.vertices[edge[1]][0],
                    c.vertices[edge[1]][1],
                    xtemp,
                    ytemp,
                    width,
                    height,
                    exX,
                    exY,
                )
            elif edge[2] >= 0:
                # Only one vertex
                if c.lines[edge[0]][1] == 0:
                    # Vertical line
                    xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0]
                    if c.vertices[edge[2]][1] > (height + exY) / 2:
                        ytemp = height + exY
                    else:
                        ytemp = 0.0 - exY
                else:
                    xtemp = 0.0 - exX
                    ytemp = c.lines[edge[0]][2] / c.lines[edge[0]][1]
                [x1, y1, x2, y2] = clip_line(
                    xtemp,
                    ytemp,
                    c.vertices[edge[2]][0],
                    c.vertices[edge[2]][1],
                    width,
                    height,
                    exX,
                    exY,
                )
            if x1 or x2 or y1 or y2:
                lines.append(
                    QgsPointXY(x1 + extent.xMinimum(), y1 + extent.yMinimum()))
                lines.append(
                    QgsPointXY(x2 + extent.xMinimum(), y2 + extent.yMinimum()))
                if 0 - exX in (x1, x2):
                    hasXMin = True
                if 0 - exY in (y1, y2):
                    hasYMin = True
                if height + exY in (y1, y2):
                    hasYMax = True
                if width + exX in (x1, x2):
                    hasXMax = True
        if hasXMin:
            if hasYMax:
                lines.append(
                    QgsPointXY(extent.xMinimum() - exX,
                               height + extent.yMinimum() + exY))
            if hasYMin:
                lines.append(
                    QgsPointXY(extent.xMinimum() - exX,
                               extent.yMinimum() - exY))
        if hasXMax:
            if hasYMax:
                lines.append(
                    QgsPointXY(width + extent.xMinimum() + exX,
                               height + extent.yMinimum() + exY))
            if hasYMin:
                lines.append(
                    QgsPointXY(width + extent.xMinimum() + exX,
                               extent.yMinimum() - exY))
        return lines
    def diamonds(self, sink, source, width, height, rotation, feedback):
        features = source.getFeatures()
        ft = QgsFeature()

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        if rotation >= 0:
            for current, feat in enumerate(features):
                if feedback.isCanceled():
                    break

                if not feat.hasGeometry():
                    continue

                w = feat[width]
                h = feat[height]
                angle = feat[rotation]
                # block 0/NULL width or height, but allow 0 as angle value
                if not w or not h:
                    feedback.pushInfo(QCoreApplication.translate('RectanglesOvalsDiamondsVariable', 'Feature {} has empty '
                                                                 'width or height. '
                                                                 'Skipping…').format(feat.id()))
                    continue
                if angle is NULL:
                    feedback.pushInfo(QCoreApplication.translate('RectanglesOvalsDiamondsVariable', 'Feature {} has empty '
                                                                 'angle. '
                                                                 'Skipping…').format(feat.id()))
                    continue

                xOffset = w / 2.0
                yOffset = h / 2.0
                phi = angle * math.pi / 180

                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)]
                polygon = [[QgsPointXY(i[0] * math.cos(phi) + i[1] * math.sin(phi) + x,
                                       -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygonXY(polygon))
                ft.setAttributes(feat.attributes())
                sink.addFeature(ft, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))
        else:
            for current, feat in enumerate(features):
                if feedback.isCanceled():
                    break

                if not feat.hasGeometry():
                    continue

                w = feat[width]
                h = feat[height]
                if not w or not h:
                    feedback.pushInfo(QCoreApplication.translate('RectanglesOvalsDiamondsVariable', 'Feature {} has empty '
                                                                 'width or height. '
                                                                 'Skipping…').format(feat.id()))
                    continue

                xOffset = w / 2.0
                yOffset = h / 2.0

                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)]
                polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygonXY(polygon))
                ft.setAttributes(feat.attributes())
                sink.addFeature(ft, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))
Ejemplo n.º 12
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        proximity = self.parameterAsDouble(parameters, self.PROXIMITY, context)
        radius = self.parameterAsDouble(parameters, self.DISTANCE, context)
        horizontal = self.parameterAsBool(parameters, self.HORIZONTAL, context)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, source.fields(),
                                               source.wkbType(),
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        features = source.getFeatures()

        total = 100.0 / source.featureCount() if source.featureCount() else 0

        def searchRect(p):
            return QgsRectangle(p.x() - proximity,
                                p.y() - proximity,
                                p.x() + proximity,
                                p.y() + proximity)

        index = QgsSpatialIndex()

        # NOTE: this is a Python port of QgsPointDistanceRenderer::renderFeature. If refining this algorithm,
        # please port the changes to QgsPointDistanceRenderer::renderFeature also!

        clustered_groups = []
        group_index = {}
        group_locations = {}
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            point = f.geometry().asPoint()

            other_features_within_radius = index.intersects(searchRect(point))
            if not other_features_within_radius:
                index.insertFeature(f)
                group = [f]
                clustered_groups.append(group)
                group_index[f.id()] = len(clustered_groups) - 1
                group_locations[f.id()] = point
            else:
                # find group with closest location to this point (may be more than one within search tolerance)
                min_dist_feature_id = other_features_within_radius[0]
                min_dist = group_locations[min_dist_feature_id].distance(point)
                for i in range(1, len(other_features_within_radius)):
                    candidate_id = other_features_within_radius[i]
                    new_dist = group_locations[candidate_id].distance(point)
                    if new_dist < min_dist:
                        min_dist = new_dist
                        min_dist_feature_id = candidate_id

                group_index_pos = group_index[min_dist_feature_id]
                group = clustered_groups[group_index_pos]

                # calculate new centroid of group
                old_center = group_locations[min_dist_feature_id]
                group_locations[min_dist_feature_id] = QgsPointXY(
                    (old_center.x() * len(group) + point.x()) /
                    (len(group) + 1.0),
                    (old_center.y() * len(group) + point.y()) /
                    (len(group) + 1.0))
                # add to a group
                clustered_groups[group_index_pos].append(f)
                group_index[f.id()] = group_index_pos

            feedback.setProgress(int(current * total))

        current = 0
        total = 100.0 / len(clustered_groups) if clustered_groups else 1
        feedback.setProgress(0)

        fullPerimeter = 2 * math.pi

        for group in clustered_groups:
            if feedback.isCanceled():
                break

            count = len(group)
            if count == 1:
                sink.addFeature(group[0], QgsFeatureSink.FastInsert)
            else:
                angleStep = fullPerimeter / count
                if count == 2 and horizontal:
                    currentAngle = math.pi / 2
                else:
                    currentAngle = 0

                old_point = group_locations[group[0].id()]

                for f in group:
                    if feedback.isCanceled():
                        break

                    sinusCurrentAngle = math.sin(currentAngle)
                    cosinusCurrentAngle = math.cos(currentAngle)
                    dx = radius * sinusCurrentAngle
                    dy = radius * cosinusCurrentAngle

                    # we want to keep any existing m/z values
                    point = f.geometry().constGet().clone()
                    point.setX(old_point.x() + dx)
                    point.setY(old_point.y() + dy)
                    f.setGeometry(QgsGeometry(point))

                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    currentAngle += angleStep

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

        return {self.OUTPUT: dest_id}
Ejemplo n.º 13
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        source = self.parameterAsSource(parameters, self.INPUT, context)
        # allow only regular point layers. no Multipoints
        if (source.wkbType() == 4 or source.wkbType() == 1004
                or source.wkbType() == 3004):
            raise QgsProcessingException("MultiPoint layer is not supported!")
        # radius = self.parameterAsString(
        #    parameters,
        #    self.RADIUS,
        #    context
        # )
        # mode = self.parameterAsEnum(
        #    parameters,
        #    self.MODES,
        #    context
        # )
        categories = self.parameterAsEnums(parameters, self.KEYS, context)
        # feedback.pushInfo(addressField)

        # If source was not found, throw an exception to indicate that the algorithm
        # encountered a fatal error. The exception text can be any string, but in this
        # case we use the pre-built invalidSourceError method to return a standard
        # helper text for when a source cannot be evaluated
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        fields = QgsFields()
        fields.append(QgsField("id", QVariant.String))
        fields.append(QgsField("origin_id", QVariant.Int))
        fields.append(QgsField("title", QVariant.String))
        fields.append(QgsField("label", QVariant.String))
        fields.append(QgsField("distance", QVariant.Double))
        fields.append(QgsField("categories", QVariant.String))
        (sink,
         dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                         fields, QgsWkbTypes.Point,
                                         QgsCoordinateReferenceSystem(4326))
        # Send some information to the user
        feedback.pushInfo('{} points for POI finding'.format(
            source.featureCount()))
        # If sink was not created, throw an exception to indicate that the algorithm
        # encountered a fatal error. The exception text can be any string, but in this
        # case we use the pre-built invalidSinkError method to return a standard
        # helper text for when a sink cannot be evaluated
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        # Compute the number of steps to display within the progress bar and
        # get features from source
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        features = source.getFeatures()
        # get the keys:
        creds = self.loadCredFunctionAlg()
        # convert categories to list for API call:
        categoriesList = []
        #self.keys[keyField].split(" | ")[1]
        for category in categories:
            categoriesList.append(self.keys[category])
        categories = ",".join(categoriesList)
        layerCRS = source.sourceCrs()
        if layerCRS != QgsCoordinateReferenceSystem(4326):
            sourceCrs = source.sourceCrs()
            destCrs = QgsCoordinateReferenceSystem(4326)
            tr = QgsCoordinateTransform(sourceCrs, destCrs,
                                        QgsProject.instance())
        for current, feature in enumerate(features):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break
            # convert coordinates:
            if layerCRS != QgsCoordinateReferenceSystem(4326):
                # we reproject:
                geom = feature.geometry()
                newGeom = tr.transform(geom.asPoint())
                x = newGeom.x()
                y = newGeom.y()
            else:
                x = feature.geometry().asPoint().x()
                y = feature.geometry().asPoint().y()
            coordinates = str(y) + "," + str(x)
            # get the location from the API:
            header = {"referer": "HQGIS"}
            ApiUrl = 'https://browse.search.hereapi.com/v1/browse?at=' + coordinates + \
                "&categories=" + categories + "&limit=100&apiKey=" + creds["id"]
            feedback.pushInfo('calling Url {}'.format(ApiUrl))
            r = requests.get(ApiUrl, headers=header)
            responsePlaces = json.loads(r.text)["items"]
            for place in responsePlaces:
                lat = place["position"]["lat"]
                lng = place["position"]["lng"]
                # iterate over categories:
                categoriesResp = []
                for cat in place["categories"]:
                    categoriesResp.append(cat["id"])
                fet = QgsFeature()
                fet.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(lng, lat)))
                fet.setAttributes([
                    place["id"],
                    feature.id(), place["title"], place["address"]["label"],
                    place["distance"], ";".join(categoriesResp)
                ])
                sink.addFeature(fet, QgsFeatureSink.FastInsert)
            #lat = responseAddress["Location"]["DisplayPosition"]["Latitude"]
            #lng = responseAddress["Location"]["DisplayPosition"]["Longitude"]
            # Add a feature in the sink
            # feedback.pushInfo(str(lat))

            # fet.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(lng,lat)))
            # fet.setAttributes([

            # Update the progress bar
            feedback.setProgress(int(current * total))

        # To run another Processing algorithm as part of this algorithm, you can use
        # processing.run(...). Make sure you pass the current context and feedback
        # to processing.run to ensure that all temporary layer outputs are available
        # to the executed algorithm, and that the executed algorithm can send feedback
        # reports to the user (and correctly handle cancelation and progress
        # reports!)

        # Return the results of the algorithm. In this case our only result is
        # the feature sink which contains the processed features, but some
        # algorithms may return multiple feature sinks, calculated numeric
        # statistics, etc. These should all be included in the returned
        # dictionary, with keys matching the feature corresponding parameter
        # or output names.
        return {self.OUTPUT: dest_id}
Ejemplo n.º 14
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS, context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = startPoints.fields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Loading start points…'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs(), context.transformContext())
        features = startPoints.getFeatures(request)
        total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0

        points = []
        source_attributes = {}
        i = 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            for p in f.geometry().vertices():
                points.append(QgsPointXY(p))
                source_attributes[i] = f.attributes()
                i += 1

            feedback.setProgress(int(current * total))

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Building graph…'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…'))
        graph = builder.graph()

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.MultiPoint, network.sourceCrs())

        vertices = []
        upperBoundary = []
        lowerBoundary = []
        total = 100.0 / len(snappedPoints) if snappedPoints else 1
        for i, p in enumerate(snappedPoints):
            if feedback.isCanceled():
                break

            idxStart = graph.findVertex(snappedPoints[i])
            origPoint = points[i].toString()

            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
            for j, v in enumerate(cost):
                if v > travelCost and tree[j] != -1:
                    vertexId = graph.edge(tree[j]).fromVertex()
                    if cost[vertexId] <= travelCost:
                        vertices.append(j)

            for j in vertices:
                upperBoundary.append(graph.vertex(graph.edge(tree[j]).toVertex()).point())
                lowerBoundary.append(graph.vertex(graph.edge(tree[j]).fromVertex()).point())

            geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
            geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

            feat.setGeometry(geomUpper)

            attrs = source_attributes[i]
            attrs.extend(['upper', origPoint])
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feat.setGeometry(geomLower)
            attrs[-2] = 'lower'
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            vertices[:] = []
            upperBoundary[:] = []
            lowerBoundary[:] = []

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 15
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)
        startPoint = self.getParameterValue(self.START_POINT)
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        tmp = startPoint.split(',')
        startPoint = QgsPointXY(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(layer, directionField, forwardValue,
                                          backwardValue, bothValue,
                                          defaultDirection)

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint])

        feedback.pushInfo(self.tr('Calculating service area...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = []
        for i, v in enumerate(cost):
            if v > travelCost and tree[i] != -1:
                vertexId = graph.edge(tree[i]).outVertex()
                if cost[vertexId] <= travelCost:
                    vertices.append(i)

        upperBoundary = []
        lowerBoundary = []
        for i in vertices:
            upperBoundary.append(
                graph.vertex(graph.edge(tree[i]).inVertex()).point())
            lowerBoundary.append(
                graph.vertex(graph.edge(tree[i]).outVertex()).point())

        feedback.pushInfo(self.tr('Writing results...'))

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
        geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

        writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter(
            fields, QgsWkbTypes.MultiPoint, layer.crs(), context)

        feat.setGeometry(geomUpper)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)

        feat.setGeometry(geomLower)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)

        del writer

        upperBoundary.append(startPoint)
        lowerBoundary.append(startPoint)
        geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
        geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

        writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter(
            fields, QgsWkbTypes.Polygon, layer.crs(), context)

        geom = geomUpper.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)

        geom = geomLower.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)
        del writer
Ejemplo n.º 16
0
    def processAlgorithm(self, parameters, context, feedback):
        spacing = self.parameterAsDouble(parameters, self.SPACING, context)
        inset = self.parameterAsDouble(parameters, self.INSET, context)
        randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
        isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
        crs = self.parameterAsCrs(parameters, self.CRS, context)
        extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point, crs)
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.0 / (area / pSpacing)
        y = extent.yMaximum() - inset

        extent_geom = QgsGeometry.fromRect(extent)
        extent_engine = QgsGeometry.createGeometryEngine(
            extent_geom.constGet())
        extent_engine.prepareGeometry()

        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if feedback.isCanceled():
                    break

                if randomize:
                    geom = QgsGeometry().fromPointXY(
                        QgsPointXY(
                            uniform(x - (pSpacing / 2.0),
                                    x + (pSpacing / 2.0)),
                            uniform(y - (pSpacing / 2.0),
                                    y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry().fromPointXY(QgsPointXY(x, y))

                if extent_engine.intersects(geom.constGet()):
                    f.setAttribute('id', count)
                    f.setGeometry(geom)
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    x += pSpacing
                    count += 1
                    feedback.setProgress(int(count * total))
            y = y - pSpacing

        return {self.OUTPUT: dest_id}
Ejemplo n.º 17
0
    def clip_voronoi(self, edges, c, width, height, extent, point, xyminmax):
        """Clip voronoi function based on code written for Inkscape.
        Copyright (C) 2010 Alvin Penner, [email protected]
        Clips one Thiessen polygon (convex polygon) to extent
        """

        pt_x = point.x() - extent.xMinimum()
        pt_y = point.y() - extent.yMinimum()
        (xmin, ymin, xmax, ymax) = xyminmax

        def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
            return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

        def clip_line(x1, y1, x2, y2, w, h):
            if x1 < 0 and x2 < 0:
                # Completely to the left
                return [0, 0, 0, 0]
            if x1 > w and x2 > w:
                # Completely to the right
                return [0, 0, 0, 0]
            if y1 < 0 and y2 < 0:
                # Completely below
                return [0, 0, 0, 0]
            if y1 > h and y2 > h:
                # Completely above
                return [0, 0, 0, 0]
            # Clip on the left envelope boundary
            if x1 < 0:
                # First point to the left
                y1 = (y1 * x2 - y2 * x1) / (x2 - x1)
                x1 = 0
            if x2 < 0:
                # Last point to the left
                y2 = (y1 * x2 - y2 * x1) / (x2 - x1)
                x2 = 0
            # Clip on the right envelope boundary
            if x1 > w:
                # First point to the right
                y1 = y1 + (w - x1) * (y2 - y1) / (x2 - x1)
                x1 = w
            if x2 > w:
                # Last point to the right
                y2 = y1 + (w - x1) * (y2 - y1) / (x2 - x1)
                x2 = w
            if isclose(x1, x2) and isclose(y1, y2):
                return [0, 0, 0, 0]
            # Clip on the bottom envelope boundary
            if y1 < 0:
                # First point below
                x1 = (x1 * y2 - x2 * y1) / (y2 - y1)
                y1 = 0
            if y2 < 0:
                # Second point below
                x2 = (x1 * y2 - x2 * y1) / (y2 - y1)
                y2 = 0
            # Clip on the top envelope boundary
            if y1 > h:
                # First point above
                x1 = x1 + (h - y1) * (x2 - x1) / (y2 - y1)
                y1 = h
            if y2 > h:
                # Second point above
                x2 = x1 + (h - y1) * (x2 - x1) / (y2 - y1)
                y2 = h
            if isclose(x1, x2) and isclose(y1, y2):
                return [0, 0, 0, 0]
            return [x1, y1, x2, y2]

        bndpoints = []
        hasXMin = False
        hasYMin = False
        hasXMax = False
        hasYMax = False
        XMinNumber = 0
        XMaxNumber = 0
        YMinNumber = 0
        YMaxNumber = 0
        # The same line may appear twice for collinear input points,
        # so have to remember which lines have contributed
        XMinLine = -1
        XMaxLine = -1
        YMinLine = -1
        YMaxLine = -1
        for edge in edges:
            if edge[1] >= 0 and edge[2] >= 0:
                # Two vertices
                [x1, y1, x2, y2
                 ] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1],
                               c.vertices[edge[2]][0], c.vertices[edge[2]][1],
                               width, height)
            elif edge[1] >= 0:
                # Only one (left) vertex
                if c.lines[edge[0]][1] == 0:
                    # Vertical line
                    #xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0]
                    xtemp = c.vertices[edge[1]][0]
                    ytemp = 0 - 1
                    #if c.vertices[edge[1]][1] > height / 2:
                    #    ytemp = height
                    #else:
                    #    ytemp = 0
                else:
                    # Create an end of the line at the right edge - OK
                    xtemp = width
                    ytemp = (c.lines[edge[0]][2] -
                             width * c.lines[edge[0]][0]) / c.lines[edge[0]][1]
                [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0],
                                             c.vertices[edge[1]][1], xtemp,
                                             ytemp, width, height)
            elif edge[2] >= 0:
                # Only one (right) vertex
                if c.lines[edge[0]][1] == 0:
                    # Vertical line
                    #xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0]
                    xtemp = c.vertices[edge[2]][0]
                    ytemp = height + 1
                    #if c.vertices[edge[2]][1] > height / 2:
                    #    ytemp = height
                    #else:
                    #    ytemp = 0.0
                else:
                    # End the line at the left edge - OK
                    xtemp = 0.0
                    ytemp = c.lines[edge[0]][2] / c.lines[edge[0]][1]
                [x1, y1, x2, y2] = clip_line(
                    xtemp,
                    ytemp,
                    c.vertices[edge[2]][0],
                    c.vertices[edge[2]][1],
                    width,
                    height,
                )
            else:
                # No vertex, only a line
                if c.lines[edge[0]][1] == 0:
                    # Vertical line - should not happen
                    xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0]
                    ytemp = 0.0
                    xend = xtemp
                    yend = height
                else:
                    # End the line at both edges - ???
                    xtemp = 0.0
                    ytemp = c.lines[edge[0]][2] / c.lines[edge[0]][1]
                    xend = width
                    yend = (c.lines[edge[0]][2] -
                            width * c.lines[edge[0]][0]) / c.lines[edge[0]][1]
                [x1, y1, x2, y2] = clip_line(
                    xtemp,
                    ytemp,
                    xend,
                    yend,
                    width,
                    height,
                )
            if x1 or x2 or y1 or y2:
                bndpoints.append(
                    QgsPointXY(x1 + extent.xMinimum(), y1 + extent.yMinimum()))
                bndpoints.append(
                    QgsPointXY(x2 + extent.xMinimum(), y2 + extent.yMinimum()))
                if 0 in (x1, x2):
                    hasXMin = True
                    if XMinLine != edge[0]:
                        XMinNumber = XMinNumber + 1
                        XMinLine = edge[0]
                if 0 in (y1, y2):
                    hasYMin = True
                    if YMinLine != edge[0]:
                        YMinNumber = YMinNumber + 1
                        YMinLine = edge[0]
                if height in (y1, y2):
                    hasYMax = True
                    if YMaxLine != edge[0]:
                        YMaxNumber = YMaxNumber + 1
                        YMaxLine = edge[0]
                if width in (x1, x2):
                    hasXMax = True
                    if XMaxLine != edge[0]:
                        XMaxNumber = XMaxNumber + 1
                        XMaxLine = edge[0]

        # Add auxiliary points for corner cases, if necessary (duplicate
        # points is not a problem - will be ignored later).
        # a) Extreme input points (lowest, leftmost, rightmost, highest)
        #    A point can be extreme on both axis
        if pt_x == xmin:  # leftmost point
            if XMinNumber == 0:
                bndpoints.append(
                    QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                bndpoints.append(
                    QgsPointXY(extent.xMinimum(), height + extent.yMinimum()))
            elif XMinNumber == 1:
                if hasYMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                elif hasYMax:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(),
                                   height + extent.yMinimum()))
        elif pt_x == xmax:  # rightmost point
            if XMaxNumber == 0:
                bndpoints.append(
                    QgsPointXY(width + extent.xMinimum(), extent.yMinimum()))
                bndpoints.append(
                    QgsPointXY(width + extent.xMinimum(),
                               height + extent.yMinimum()))
            elif XMaxNumber == 1:
                if hasYMin:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   extent.yMinimum()))
                elif hasYMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   height + extent.yMinimum()))
        if pt_y == ymin:  # lowest point
            if YMinNumber == 0:
                bndpoints.append(
                    QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                bndpoints.append(
                    QgsPointXY(width + extent.xMinimum(), extent.yMinimum()))
            elif YMinNumber == 1:
                if hasXMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                elif hasXMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   extent.yMinimum()))
        elif pt_y == ymax:  # highest point
            if YMaxNumber == 0:
                bndpoints.append(
                    QgsPointXY(extent.xMinimum(), height + extent.yMinimum()))
                bndpoints.append(
                    QgsPointXY(width + extent.xMinimum(),
                               height + extent.yMinimum()))
            elif YMaxNumber == 1:
                if hasXMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(),
                                   height + extent.yMinimum()))
                elif hasXMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   height + extent.yMinimum()))
        # b) Polygon that covers the x or the y extent:
        if hasYMin and hasYMax:
            if YMaxNumber > 1:
                if hasXMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                elif hasXMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   extent.yMinimum()))
            elif YMinNumber > 1:
                if hasXMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(),
                                   height + extent.yMinimum()))
                elif hasXMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   height + extent.yMinimum()))
        elif hasXMin and hasXMax:
            if XMaxNumber > 1:
                if hasYMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                elif hasYMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   extent.yMinimum()))
            elif XMinNumber > 1:
                if hasYMin:
                    bndpoints.append(
                        QgsPointXY(extent.xMinimum(),
                                   height + extent.yMinimum()))
                elif hasYMax:
                    bndpoints.append(
                        QgsPointXY(width + extent.xMinimum(),
                                   height + extent.yMinimum()))
        # c) Simple corners:
        if XMinNumber == 1 and YMinNumber == 1 and not hasXMax and not hasYMax:
            bndpoints.append(QgsPointXY(extent.xMinimum(), extent.yMinimum()))
        if XMinNumber == 1 and YMaxNumber == 1 and not hasXMax and not hasYMin:
            bndpoints.append(
                QgsPointXY(extent.xMinimum(), height + extent.yMinimum()))
        if XMaxNumber == 1 and YMinNumber == 1 and not hasXMin and not hasYMax:
            bndpoints.append(
                QgsPointXY(width + extent.xMinimum(), extent.yMinimum()))
        if XMaxNumber == 1 and YMaxNumber == 1 and not hasXMin and not hasYMin:
            bndpoints.append(
                QgsPointXY(width + extent.xMinimum(),
                           height + extent.yMinimum()))
        return bndpoints
Ejemplo n.º 18
0
 def testQgsGeometryRepr(self):
     p = QgsPointXY(123.456, 987.654)
     g = QgsGeometry.fromPointXY(p)
     self.assertTrue(g.__repr__().startswith('<QgsGeometry: Point (123.456'))
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        azimuthmode = self.parameterAsInt(parameters, self.PrmAzimuthMode,
                                          context)
        startanglecol = self.parameterAsString(parameters,
                                               self.PrmAzimuth1Field, context)
        endanglecol = self.parameterAsString(parameters, self.PrmAzimuth2Field,
                                             context)
        radiusCol = self.parameterAsString(parameters, self.PrmRadiusField,
                                           context)
        startangle = self.parameterAsDouble(parameters,
                                            self.PrmDefaultAzimuth1, context)
        endangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth2,
                                          context)
        radius = self.parameterAsDouble(parameters, self.PrmDefaultRadius,
                                        context)
        segments = self.parameterAsInt(parameters, self.PrmDrawingSegments,
                                       context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                    context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        measureFactor = conversionToMeters(units)

        radius *= measureFactor

        ptSpacing = 360.0 / segments
        srcCRS = source.sourceCrs()
        fields = source.fields()
        if export_geom:
            names = fields.names()
            name_x, name_y = settings.getGeomNames(names)
            fields.append(QgsField(name_x, QVariant.Double))
            fields.append(QgsField(name_y, QVariant.Double))
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                                                   self.PrmOutputLayer,
                                                   context, fields,
                                                   QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, fields,
                                             QgsWkbTypes.LineString, srcCRS)

        if srcCRS != epsg4326:
            geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326,
                                                QgsProject.instance())
            toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS,
                                               QgsProject.instance())

        featureCount = source.featureCount()
        total = 100.0 / featureCount if featureCount else 0

        numbad = 0
        iterator = source.getFeatures()
        for cnt, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                pts = []
                pt = feature.geometry().asPoint()
                pt_orig_x = pt.x()
                pt_orig_y = pt.y()
                # make sure the coordinates are in EPSG:4326
                if srcCRS != epsg4326:
                    pt = geomTo4326.transform(pt.x(), pt.y())
                pts.append(pt)
                if startanglecol:
                    sangle = float(feature[startanglecol])
                else:
                    sangle = startangle
                if endanglecol:
                    eangle = float(feature[endanglecol])
                else:
                    eangle = endangle
                if azimuthmode == 1:
                    width = abs(eangle) / 2.0
                    eangle = sangle + width
                    sangle -= width
                if radiusCol:
                    dist = float(feature[radiusCol]) * measureFactor
                else:
                    dist = radius

                sangle = sangle % 360
                eangle = eangle % 360

                if sangle > eangle:
                    # We are crossing the 0 boundry so lets just subtract
                    # 360 from it.
                    sangle -= 360.0
                while sangle < eangle:
                    g = geod.Direct(pt.y(), pt.x(), sangle, dist,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    sangle += ptSpacing  # add this number of degrees to the angle

                g = geod.Direct(pt.y(), pt.x(), eangle, dist,
                                Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                pts.append(pt)

                makeIdlCrossingsPositive(pts)
                # If the Output crs is not 4326 transform the points to the proper crs
                if srcCRS != epsg4326:
                    for x, ptout in enumerate(pts):
                        pts[x] = toSinkCrs.transform(ptout)

                f = QgsFeature()
                if shapetype == 0:
                    f.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                else:
                    f.setGeometry(QgsGeometry.fromPolylineXY(pts))
                attr = feature.attributes()
                if export_geom:
                    attr.append(pt_orig_x)
                    attr.append(pt_orig_y)
                f.setAttributes(attr)
                sink.addFeature(f)
            except Exception:
                numbad += 1

            if cnt % 100 == 0:
                feedback.setProgress(int(cnt * total))

        if numbad > 0:
            feedback.pushInfo(
                tr("{} out of {} features had invalid parameters and were ignored."
                   .format(numbad, featureCount)))

        return {self.PrmOutputLayer: dest_id}
Ejemplo n.º 20
0
 def testQgsPointXYRepr(self):
     p = QgsPointXY(123.456, 987.654)
     self.assertTrue(p.__repr__().startswith('<QgsPointXY: POINT(123.456'))
Ejemplo n.º 21
0
    def _hexagonGrid(self, sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback):
        feat = QgsFeature()

        # To preserve symmetry, hspacing is fixed relative to vspacing
        xVertexLo = 0.288675134594813 * vSpacing
        xVertexHi = 0.577350269189626 * vSpacing
        hSpacing = xVertexLo + xVertexHi

        hOverlay = hSpacing - hOverlay
        if hOverlay < 0:
            raise QgsProcessingException(
                self.tr('To preserve symmetry, hspacing is fixed relative to vspacing\n \
                        hspacing is fixed at: {0} and hoverlay is fixed at: {1}\n \
                        hoverlay cannot be negative. Increase hoverlay.').format(hSpacing, hOverlay)
            )

        halfVSpacing = vSpacing / 2.0

        columns = int(math.ceil(float(bbox.width()) / hOverlay))
        rows = int(math.ceil(float(bbox.height()) / (vSpacing - vOverlay)))

        cells = rows * columns
        count_update = cells * 0.05

        id = 1
        count = 0

        for col in range(columns):
            if feedback.isCanceled():
                break

            # (column + 1) and (row + 1) calculation is used to maintain
            # topology between adjacent shapes and avoid overlaps/holes
            # due to rounding errors
            x1 = bbox.xMinimum() + (col * hOverlay)                # far left
            x2 = x1 + (xVertexHi - xVertexLo)              # left
            x3 = bbox.xMinimum() + (col * hOverlay) + hSpacing     # right
            x4 = x3 + (xVertexHi - xVertexLo)              # far right

            for row in range(rows):
                if (col % 2) == 0:
                    y1 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 0) * halfVSpacing)  # hi
                    y2 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 1) * halfVSpacing)  # mid
                    y3 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 2) * halfVSpacing)  # lo
                else:
                    y1 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 1) * halfVSpacing)  # hi
                    y2 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 2) * halfVSpacing)  # mid
                    y3 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 3) * halfVSpacing)  # lo

                polyline = []
                polyline.append(QgsPointXY(x1, y2))
                polyline.append(QgsPointXY(x2, y1))
                polyline.append(QgsPointXY(x3, y1))
                polyline.append(QgsPointXY(x4, y2))
                polyline.append(QgsPointXY(x3, y3))
                polyline.append(QgsPointXY(x2, y3))
                polyline.append(QgsPointXY(x1, y2))

                feat.setGeometry(QgsGeometry.fromPolygonXY([polyline]))
                feat.setAttributes([x1, y1, x4, y3, id])
                sink.addFeature(feat, QgsFeatureSink.FastInsert)
                id += 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    feedback.setProgress(int(count / cells * 100))
Ejemplo n.º 22
0
    def processAlgorithm(self, parameters, context, feedback):
        # Get variables from dialog
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        field_name = self.parameterAsString(parameters, self.FIELD, context)
        kneighbors = self.parameterAsInt(parameters, self.KNEIGHBORS, context)
        use_field = bool(field_name)

        field_index = -1

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))

        current = 0

        # Get properties of the field the grouping is based on
        if use_field:
            field_index = source.fields().lookupField(field_name)
            if field_index >= 0:
                fields.append(
                    source.fields()[field_index]
                )  # Add a field with the name of the grouping field

                # Initialize writer
                (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                       context, fields,
                                                       QgsWkbTypes.Polygon,
                                                       source.sourceCrs())
                if sink is None:
                    raise QgsProcessingException(
                        self.invalidSinkError(parameters, self.OUTPUT))

                success = False
                fid = 0

                # Get unique values of grouping field
                unique_values = source.uniqueValues(field_index)
                total = 100.0 / float(
                    source.featureCount() * len(unique_values))

                for unique in unique_values:
                    points = []
                    filter = QgsExpression.createFieldEqualityExpression(
                        field_name, unique)
                    request = QgsFeatureRequest().setFilterExpression(filter)
                    request.setSubsetOfAttributes([])
                    # Get features with the grouping attribute equal to the current grouping value
                    features = source.getFeatures(request)
                    for in_feature in features:
                        if feedback.isCanceled():
                            break
                        # Add points or vertices of more complex geometry
                        points.extend(extract_points(in_feature.geometry()))
                        current += 1
                        feedback.setProgress(int(current * total))
                    # A minimum of 3 points is necessary to proceed
                    if len(points) >= 3:
                        out_feature = QgsFeature()
                        the_hull = concave_hull(points, kneighbors)
                        if the_hull:
                            vertex = [
                                QgsPointXY(point[0], point[1])
                                for point in the_hull
                            ]
                            poly = QgsGeometry().fromPolygonXY([vertex])

                            out_feature.setGeometry(poly)
                            # Give the polygon the same attribute as the point grouping attribute
                            out_feature.setAttributes([fid, unique])
                            sink.addFeature(out_feature,
                                            QgsFeatureSink.FastInsert)
                            success = True  # at least one polygon created
                    fid += 1
                if not success:
                    raise QgsProcessingException(
                        'No hulls could be created. Most likely there were not at least three unique points in any of the groups.'
                    )
            else:
                # Field parameter provided but can't read from it
                raise QgsProcessingException('Unable to find grouping field')

        else:
            # Not grouped by field
            # Initialize writer
            (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                   context, fields,
                                                   QgsWkbTypes.Polygon,
                                                   source.sourceCrs())
            if sink is None:
                raise QgsProcessingException(
                    self.invalidSinkError(parameters, self.OUTPUT))

            points = []
            request = QgsFeatureRequest()
            request.setSubsetOfAttributes([])
            features = source.getFeatures(request)  # Get all features
            total = 100.0 / source.featureCount() if source.featureCount(
            ) else 0
            for in_feature in features:
                if feedback.isCanceled():
                    break
                # Add points or vertices of more complex geometry
                points.extend(extract_points(in_feature.geometry()))
                current += 1
                feedback.setProgress(int(current * total))

            # A minimum of 3 points is necessary to proceed
            if len(points) >= 3:
                out_feature = QgsFeature()
                the_hull = concave_hull(points, kneighbors)
                if the_hull:
                    vertex = [
                        QgsPointXY(point[0], point[1]) for point in the_hull
                    ]
                    poly = QgsGeometry().fromPolygonXY([vertex])

                    out_feature.setGeometry(poly)
                    out_feature.setAttributes([0])
                    sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
                else:
                    # the_hull returns None only when there are less than three points after cleaning
                    raise QgsProcessingException(
                        'At least three unique points are required to create a concave hull.'
                    )
            else:
                raise QgsProcessingException(
                    'At least three points are required to create a concave hull.'
                )

        return {self.OUTPUT: dest_id}
Ejemplo n.º 23
0
    def test_resetSnappingIndex(self):
        self.pointsLayer.setDependencies([])
        self.linesLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(self.pointsLayer,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)

        m = u.snapToMap(QPoint(95, 100))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(1, 0))

        f = QgsFeature(self.linesLayer.fields())
        f.setId(1)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()

        l1 = len([f for f in self.pointsLayer.getFeatures()])
        self.assertEqual(l1, 4)
        m = u.snapToMap(QPoint(95, 0))
        # snapping not updated
        self.pointsLayer.setDependencies([])
        self.assertEqual(m.isValid(), False)

        # set layer dependencies
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(2)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the snapped point is OK
        m = u.snapToMap(QPoint(45, 50))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.5, 0.5))
        self.pointsLayer.setDependencies([])

        # test chained layer dependencies A -> B -> C
        cfg.setIndividualLayerSettings(self.pointsLayer2,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(3)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is OK
        m = u.snapToMap(QPoint(75, 100 - 80))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.7, 0.8))
        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
Ejemplo n.º 24
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER,
                                            context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE,
                                             context)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink,
         dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                         fields, QgsWkbTypes.Point,
                                         source.sourceCrs(),
                                         QgsFeatureSink.RegeneratePrimaryKey)
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        featureCount = source.featureCount()
        total = 100.0 / pointCount if pointCount else 1

        index = QgsSpatialIndex()
        points = dict()

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        request = QgsFeatureRequest()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            if feedback.isCanceled():
                break

            # pick random feature
            fid = random.randint(0, featureCount - 1)
            f = next(
                source.getFeatures(
                    request.setFilterFid(fid).setSubsetOfAttributes([])))
            fGeom = f.geometry()

            if fGeom.isMultipart():
                lines = fGeom.asMultiPolyline()
                # pick random line
                lineId = random.randint(0, len(lines) - 1)
                vertices = lines[lineId]
            else:
                vertices = fGeom.asPolyline()

            # pick random segment
            if len(vertices) == 2:
                vid = 0
            else:
                vid = random.randint(0, len(vertices) - 2)
            startPoint = vertices[vid]
            endPoint = vertices[vid + 1]
            length = da.measureLine(startPoint, endPoint)
            dist = length * random.random()

            if dist > minDistance:
                d = dist / (length - dist)
                rx = (startPoint.x() + d * endPoint.x()) / (1 + d)
                ry = (startPoint.y() + d * endPoint.y()) / (1 + d)

                # generate random point
                p = QgsPointXY(rx, ry)
                geom = QgsGeometry.fromPointXY(p)
                if vector.checkMinDistance(p, index, minDistance, points):
                    f = QgsFeature(nPoints)
                    f.initAttributes(1)
                    f.setFields(fields)
                    f.setAttribute('id', nPoints)
                    f.setGeometry(geom)
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    index.addFeature(f)
                    points[nPoints] = p
                    nPoints += 1
                    feedback.setProgress(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            feedback.pushInfo(
                self.tr(
                    'Could not generate requested number of random points. '
                    'Maximum number of attempts exceeded.'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 25
0
from qgis.core import (
    QgsFeature,
    QgsGeometry,
    QgsPointXY,
    QgsFeatureRequest,
    QgsExpression,
    QgsProject,
    QgsOfflineEditing,
)


# Tet features, fields: [id, name, geometry]
# "id" is used as a pk to retriev features by attribute
TEST_FEATURES = [
    (1, 'name 1', QgsPointXY(9, 45)),
    (2, 'name 2', QgsPointXY(9.5, 45.5)),
    (3, 'name 3', QgsPointXY(9.5, 46)),
    (4, 'name 4', QgsPointXY(10, 46.5)),
]

# Additional features for insert test
TEST_FEATURES_INSERT = [
    (5, 'name 5', QgsPointXY(9.7, 45.7)),
    (6, 'name 6', QgsPointXY(10.6, 46.6)),
]


class OfflineTestBase(object):

    """Generic test methods for all online providers"""
Ejemplo n.º 26
0
 def setUp(self):
     self.mPoint = QgsPointXY(10.0, 10.0)
Ejemplo n.º 27
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER,
                                            context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE,
                                             context)

        bbox = source.sourceExtent()
        sourceIndex = QgsSpatialIndex(source, feedback)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point,
                                               source.sourceCrs())

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount if pointCount else 1

        index = QgsSpatialIndex()
        points = dict()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            if feedback.isCanceled():
                break

            rx = bbox.xMinimum() + bbox.width() * random.random()
            ry = bbox.yMinimum() + bbox.height() * random.random()

            p = QgsPointXY(rx, ry)
            geom = QgsGeometry.fromPointXY(p)
            ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox())
            if len(ids) > 0 and \
                    vector.checkMinDistance(p, index, minDistance, points):
                request = QgsFeatureRequest().setFilterFids(
                    ids).setSubsetOfAttributes([])
                for f in source.getFeatures(request):
                    if feedback.isCanceled():
                        break

                    tmpGeom = f.geometry()
                    if geom.within(tmpGeom):
                        f = QgsFeature(nPoints)
                        f.initAttributes(1)
                        f.setFields(fields)
                        f.setAttribute('id', nPoints)
                        f.setGeometry(geom)
                        sink.addFeature(f, QgsFeatureSink.FastInsert)
                        index.insertFeature(f)
                        points[nPoints] = p
                        nPoints += 1
                        feedback.setProgress(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            feedback.pushInfo(
                self.tr(
                    'Could not generate requested number of random points. '
                    'Maximum number of attempts exceeded.'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 28
0
    def testDateTimeWriteShapefile(self):
        """Check writing date and time fields to an ESRI shapefile."""
        ml = QgsVectorLayer(
            ('Point?crs=epsg:4326&field=id:int&'
             'field=date_f:date&field=time_f:time&field=dt_f:datetime'),
            'test', 'memory')

        self.assertTrue(ml.isValid())
        provider = ml.dataProvider()
        self.assertIsNotNone(provider)

        ft = QgsFeature()
        ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10)))
        ft.setAttributes([
            1,
            QDate(2014, 3, 5),
            QTime(13, 45, 22),
            QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22))
        ])
        res, features = provider.addFeatures([ft])
        self.assertTrue(res)
        self.assertTrue(features)

        dest_file_name = os.path.join(str(QDir.tempPath()), 'datetime.shp')
        crs = QgsCoordinateReferenceSystem()
        crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile')
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        # Open result and check
        created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name),
                                       'test', 'ogr')

        fields = created_layer.dataProvider().fields()
        self.assertEqual(
            fields.at(fields.indexFromName('date_f')).type(), QVariant.Date)
        # shapefiles do not support time types, result should be string
        self.assertEqual(
            fields.at(fields.indexFromName('time_f')).type(), QVariant.String)
        # shapefiles do not support datetime types, result should be string
        self.assertEqual(
            fields.at(fields.indexFromName('dt_f')).type(), QVariant.String)

        f = next(created_layer.getFeatures(QgsFeatureRequest()))

        date_idx = created_layer.fields().lookupField('date_f')
        self.assertIsInstance(f.attributes()[date_idx], QDate)
        self.assertEqual(f.attributes()[date_idx], QDate(2014, 3, 5))
        time_idx = created_layer.fields().lookupField('time_f')
        # shapefiles do not support time types
        self.assertIsInstance(f.attributes()[time_idx], str)
        self.assertEqual(f.attributes()[time_idx], '13:45:22')
        # shapefiles do not support datetime types
        datetime_idx = created_layer.fields().lookupField('dt_f')
        self.assertIsInstance(f.attributes()[datetime_idx], str)
        self.assertEqual(
            f.attributes()[datetime_idx],
            QDateTime(QDate(2014, 3, 5),
                      QTime(13, 45, 22)).toString("yyyy/MM/dd hh:mm:ss.zzz"))
Ejemplo n.º 29
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        fields = QgsFields()
        fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())

        pts = []
        ptDict = {}
        ptNdx = -1
        c = voronoi.Context()
        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            geom = QgsGeometry(inFeat.geometry())
            if geom.isNull():
                continue
            if geom.isMultipart():
                points = geom.asMultiPoint()
            else:
                points = [geom.asPoint()]
            for n, point in enumerate(points):
                x = point.x()
                y = point.y()
                pts.append((x, y))
                ptNdx += 1
                ptDict[ptNdx] = (inFeat.id(), n)
            feedback.setProgress(int(current * total))

        if len(pts) < 3:
            raise QgsProcessingException(
                self.tr('Input file should contain at least 3 points. Choose '
                        'another file and try again.'))

        uniqueSet = set(item for item in pts)
        ids = [pts.index(item) for item in uniqueSet]
        sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet])
        c.triangulate = True
        voronoi.voronoi(sl, c)
        triangles = c.triangles
        feat = QgsFeature()

        total = 100.0 / len(triangles) if triangles else 1
        for current, triangle in enumerate(triangles):
            if feedback.isCanceled():
                break

            indices = list(triangle)
            indices.append(indices[0])
            polygon = []
            attrs = []
            step = 0
            for index in indices:
                fid, n = ptDict[ids[index]]
                request = QgsFeatureRequest().setFilterFid(fid)
                inFeat = next(source.getFeatures(request))
                geom = QgsGeometry(inFeat.geometry())
                if geom.isMultipart():
                    point = QgsPointXY(geom.asMultiPoint()[n])
                else:
                    point = QgsPointXY(geom.asPoint())
                polygon.append(point)
                if step <= 3:
                    attrs.append(ids[index])
                step += 1
            feat.setAttributes(attrs)
            geometry = QgsGeometry().fromPolygonXY([polygon])
            feat.setGeometry(geometry)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 30
0
 def testGettersSetters(self):
     segment = QgsLineSegment2D(QgsPointXY(1, 2), QgsPointXY(3, 4))
     self.assertEqual(segment.start(), QgsPointXY(1, 2))
     self.assertEqual(segment.end(), QgsPointXY(3, 4))
     self.assertEqual(segment.startX(), 1)
     self.assertEqual(segment.startY(), 2)
     self.assertEqual(segment.endX(), 3)
     self.assertEqual(segment.endY(), 4)
     segment.setStartX(5)
     self.assertEqual(segment.start(), QgsPointXY(5, 2))
     self.assertEqual(segment.end(), QgsPointXY(3, 4))
     self.assertEqual(segment.startX(), 5)
     self.assertEqual(segment.startY(), 2)
     self.assertEqual(segment.endX(), 3)
     self.assertEqual(segment.endY(), 4)
     segment.setStartY(6)
     self.assertEqual(segment.start(), QgsPointXY(5, 6))
     self.assertEqual(segment.end(), QgsPointXY(3, 4))
     self.assertEqual(segment.startX(), 5)
     self.assertEqual(segment.startY(), 6)
     self.assertEqual(segment.endX(), 3)
     self.assertEqual(segment.endY(), 4)
     segment.setEndX(7)
     self.assertEqual(segment.start(), QgsPointXY(5, 6))
     self.assertEqual(segment.end(), QgsPointXY(7, 4))
     self.assertEqual(segment.startX(), 5)
     self.assertEqual(segment.startY(), 6)
     self.assertEqual(segment.endX(), 7)
     self.assertEqual(segment.endY(), 4)
     segment.setEndY(8)
     self.assertEqual(segment.start(), QgsPointXY(5, 6))
     self.assertEqual(segment.end(), QgsPointXY(7, 8))
     self.assertEqual(segment.startX(), 5)
     self.assertEqual(segment.startY(), 6)
     self.assertEqual(segment.endX(), 7)
     self.assertEqual(segment.endY(), 8)
     segment.setStart(QgsPointXY(1, 2))
     self.assertEqual(segment.start(), QgsPointXY(1, 2))
     self.assertEqual(segment.end(), QgsPointXY(7, 8))
     self.assertEqual(segment.startX(), 1)
     self.assertEqual(segment.startY(), 2)
     self.assertEqual(segment.endX(), 7)
     self.assertEqual(segment.endY(), 8)
     segment.setEnd(QgsPointXY(3, 4))
     self.assertEqual(segment.start(), QgsPointXY(1, 2))
     self.assertEqual(segment.end(), QgsPointXY(3, 4))
     self.assertEqual(segment.startX(), 1)
     self.assertEqual(segment.startY(), 2)
     self.assertEqual(segment.endX(), 3)
     self.assertEqual(segment.endY(), 4)