def ovals(self, sink, source, width, height, rotation, segments, feedback):
        features = source.getFeatures()
        ft = QgsFeature()

        xOffset = width / 2.0
        yOffset = height / 2.0

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        if rotation is not None:
            phi = rotation * math.pi / 180
            for current, feat in enumerate(features):
                if feedback.isCanceled():
                    break

                if not feat.hasGeometry():
                    continue

                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

                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))
Example #2
0
 def testQgsPolygonRepr(self):
     p = QgsGeometry.fromPolygonXY(
         [[QgsPointXY(0, 0),
           QgsPointXY(2, 0),
           QgsPointXY(2, 2),
           QgsPointXY(0, 2),
           QgsPointXY(0, 0)]])
     self.assertEqual(p.constGet().__repr__(), '<QgsPolygon: Polygon ((0 0, 2 0, 2 2, 0 2, 0 0))>')
Example #3
0
def createLayerWithOnePolygon():
    layer = QgsVectorLayer("Polygon?crs=epsg:3111&field=pk:int", "vl", "memory")
    assert layer.isValid()
    f1 = QgsFeature(layer.dataProvider().fields(), 1)
    f1.setAttribute("pk", 1)
    f1.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(2484588, 2425722), QgsPointXY(2482767, 2398853), QgsPointXY(2520109, 2397715), QgsPointXY(2520792, 2425494), QgsPointXY(2484588, 2425722)]]))
    assert layer.dataProvider().addFeatures([f1])
    return layer
Example #4
0
    def _diamondGrid(self, sink, width, height, originX, originY,
                     hSpacing, vSpacing, hOverlay, vOverlay, feedback):
        ft = QgsFeature()

        halfHSpacing = hSpacing / 2
        halfVSpacing = vSpacing / 2

        halfHOverlay = hOverlay / 2
        halfVOverlay = vOverlay / 2

        columns = int(math.ceil(float(width) / (halfHSpacing - halfHOverlay)))
        rows = int(math.ceil(float(height) / (vSpacing - halfVOverlay)))

        cells = rows * columns
        count_update = cells * 0.05

        id = 1
        count = 0

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

            x = originX - (col * halfHOverlay)
            x1 = x + ((col + 0) * halfHSpacing)
            x2 = x + ((col + 1) * halfHSpacing)
            x3 = x + ((col + 2) * halfHSpacing)

            for row in range(rows):
                y = originY + (row * halfVOverlay)
                if (col % 2) == 0:
                    y1 = y - (((row * 2) + 0) * halfVSpacing)
                    y2 = y - (((row * 2) + 1) * halfVSpacing)
                    y3 = y - (((row * 2) + 2) * halfVSpacing)
                else:
                    y1 = y - (((row * 2) + 1) * halfVSpacing)
                    y2 = y - (((row * 2) + 2) * halfVSpacing)
                    y3 = y - (((row * 2) + 3) * halfVSpacing)

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

                ft.setGeometry(QgsGeometry.fromPolygonXY([polyline]))
                ft.setAttributes([x1, y1, x3, y3, id])
                sink.addFeature(ft, QgsFeatureSink.FastInsert)
                id += 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    feedback.setProgress(int(count / cells * 100))
    def create_cell(self, centroid, from_deg, to_deg, radius):
        step = abs(to_deg - from_deg) / self.DEFAULT_SEGS

        outer_ring = []
        outer_ring.append(centroid)

        # second outer
        for index in range(self.DEFAULT_SEGS, -1, -1):
            radian = math.radians(from_deg + (index * step))
            outer_ring.append(self.create_point(centroid, radian, radius))

        return QgsGeometry.fromPolygonXY([outer_ring])
Example #6
0
    def rotation_test(self):
        # We will create a polygon layer with a rotated rectangle.
        # Then we will make it the object layer for the atlas,
        # rotate the map and test that the bounding rectangle
        # is smaller than the bounds without rotation.
        polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory')
        poly = QgsFeature(polygonLayer.fields())
        points = [(10, 15), (15, 10), (45, 40), (40, 45)]
        poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]]))
        polygonLayer.dataProvider().addFeatures([poly])
        QgsProject.instance().addMapLayer(polygonLayer)

        # Recreating the layout locally
        composition = QgsPrintLayout(QgsProject.instance())
        composition.initializeDefaults()

        # the atlas map
        atlasMap = QgsLayoutItemMap(composition)
        atlasMap.attemptSetSceneRect(QRectF(20, 20, 130, 130))
        atlasMap.setFrameEnabled(True)
        atlasMap.setLayers([polygonLayer])
        atlasMap.setExtent(QgsRectangle(0, 0, 100, 50))
        composition.addLayoutItem(atlasMap)

        # the atlas
        atlas = composition.atlas()
        atlas.setCoverageLayer(polygonLayer)
        atlas.setEnabled(True)

        atlasMap.setAtlasDriven(True)
        atlasMap.setAtlasScalingMode(QgsLayoutItemMap.Auto)
        atlasMap.setAtlasMargin(0.0)

        # Testing
        atlasMap.setMapRotation(0.0)
        atlas.beginRender()
        atlas.first()
        nonRotatedExtent = QgsRectangle(atlasMap.extent())

        atlasMap.setMapRotation(45.0)
        atlas.first()
        rotatedExtent = QgsRectangle(atlasMap.extent())

        self.assertLess(rotatedExtent.width(), nonRotatedExtent.width() * 0.9)
        self.assertLess(rotatedExtent.height(), nonRotatedExtent.height() * 0.9)

        QgsProject.instance().removeMapLayer(polygonLayer)
Example #7
0
 def create_ring_cell(self, centroid, from_deg, to_deg, from_radius, to_radius):
     step = abs(to_deg - from_deg) / self.DEFAULT_SEGS
     radian = 0.0
     
     outer_ring = []
     
     # first interior
     for index in range(self.DEFAULT_SEGS  + 1 - self.GAPS):
         radian = math.radians(from_deg + (index * step))
         outer_ring.append(self.create_point(centroid, radian, from_radius))
     
     # second outer
     for index in range(self.DEFAULT_SEGS - self.GAPS, -1, -1):
         radian = math.radians(from_deg + (index * step))
         outer_ring.append(self.create_point(centroid, radian, to_radius))
         
     return QgsGeometry.fromPolygonXY([outer_ring])
    def rotation_test(self):
        # We will create a polygon layer with a rotated rectangle.
        # Then we will make it the object layer for the atlas,
        # rotate the map and test that the bounding rectangle
        # is smaller than the bounds without rotation.
        polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory')
        poly = QgsFeature(polygonLayer.pendingFields())
        points = [(10, 15), (15, 10), (45, 40), (40, 45)]
        poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]]))
        polygonLayer.dataProvider().addFeatures([poly])
        QgsProject.instance().addMapLayer(polygonLayer)

        # Recreating the composer locally
        composition = QgsComposition(QgsProject.instance())
        composition.setPaperSize(297, 210)

        # the atlas map
        atlasMap = QgsComposerMap(composition, 20, 20, 130, 130)
        atlasMap.setFrameEnabled(True)
        atlasMap.setLayers([polygonLayer])
        atlasMap.setNewExtent(QgsRectangle(0, 0, 100, 50))
        composition.addComposerMap(atlasMap)

        # the atlas
        atlas = composition.atlasComposition()
        atlas.setCoverageLayer(polygonLayer)
        atlas.setEnabled(True)
        composition.setAtlasMode(QgsComposition.ExportAtlas)

        atlasMap.setAtlasDriven(True)
        atlasMap.setAtlasScalingMode(QgsComposerMap.Auto)
        atlasMap.setAtlasMargin(0.0)

        # Testing
        atlasMap.setMapRotation(0.0)
        atlas.firstFeature()
        nonRotatedExtent = QgsRectangle(atlasMap.currentMapExtent())

        atlasMap.setMapRotation(45.0)
        atlas.firstFeature()
        rotatedExtent = QgsRectangle(atlasMap.currentMapExtent())

        assert rotatedExtent.width() < nonRotatedExtent.width() * 0.9
        assert rotatedExtent.height() < nonRotatedExtent.height() * 0.9

        QgsProject.instance().removeMapLayer(polygonLayer)
Example #9
0
    def testMeasurePolygon(self):
        # +-+-+
        # |   |
        # + +-+
        # | |
        # +-+
        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0),
            ]]
        )

        da = QgsDistanceArea()
        area = da.measureArea(polygon)
        assert area == 3, 'Expected:\n%f\nGot:\n%f\n' % (3, area)

        perimeter = da.measurePerimeter(polygon)
        assert perimeter == 8, 'Expected:\n%f\nGot:\n%f\n' % (8, perimeter)
def _swap_qgs_geometry(qgsgeom):
    if qgsgeom.wkbType() == QgsWkbTypes.Point:
        p = qgsgeom.asPoint()
        qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0]))
    elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint:
        mp = qgsgeom.asMultiPoint()
        qgsgeom = QgsGeometry.fromMultiPointXY([QgsPointXY(p[1], p[0]) for p in mp])
    elif qgsgeom.wkbType() == QgsWkbTypes.LineString:
        pl = qgsgeom.asPolyline()
        qgsgeom = QgsGeometry.fromPolylineXY([QgsPointXY(p[1],p[0]) for p in pl])
    elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString:
        mls = qgsgeom.asMultiPolyline()
        qgsgeom = QgsGeometry.fromMultiPolylineXY([[QgsPointXY(p[1],p[0]) for p in pl] for pl in mls])
    elif qgsgeom.wkbType() == QgsWkbTypes.Polygon:
        pl = qgsgeom.asPolygon()
        qgsgeom = QgsGeometry.fromPolygonXY([[QgsPointXY(p[1],p[0]) for p in r] for r in pl])
    elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon:
        mp = qgsgeom.asMultiPolygon()
        qgsgeom = QgsGeometry.fromMultiPolygonXY([[[QgsPointXY(p[1],p[0]) for p in r] for r in pl] for pl in mp])
    return qgsgeom
Example #11
0
    def testMeasurePolygonWithHole(self):
        # +-+-+-+
        # |     |
        # + +-+ +
        # | | | |
        # + +-+ +
        # |     |
        # +-+-+-+
        polygon = QgsGeometry.fromPolygonXY(
            [
                [QgsPointXY(0, 0), QgsPointXY(3, 0), QgsPointXY(3, 3), QgsPointXY(0, 3), QgsPointXY(0, 0)],
                [QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(1, 2), QgsPointXY(1, 1)],
            ]
        )
        da = QgsDistanceArea()
        area = da.measureArea(polygon)
        assert area == 8, "Expected:\n%f\nGot:\n%f\n" % (8, area)

# MH150729: Changed behavior to consider inner rings for perimeter calculation. Therefore, expected result is 16.
        perimeter = da.measurePerimeter(polygon)
        assert perimeter == 16, "Expected:\n%f\nGot:\n%f\n" % (16, perimeter)
Example #12
0
    def _rectangleGrid(self, sink, width, height, originX, originY,
                       hSpacing, vSpacing, hOverlay, vOverlay, feedback):
        ft = QgsFeature()

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

        cells = rows * columns
        count_update = cells * 0.05

        id = 1
        count = 0

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

            x1 = originX + (col * hSpacing - col * hOverlay)
            x2 = x1 + hSpacing

            for row in range(rows):
                y1 = originY - (row * vSpacing - row * vOverlay)
                y2 = y1 - vSpacing

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

                ft.setGeometry(QgsGeometry.fromPolygonXY([polyline]))
                ft.setAttributes([x1, y1, x2, y2, id])
                sink.addFeature(ft, QgsFeatureSink.FastInsert)

                id += 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    feedback.setProgress(int(count / cells * 100))
    def processEllipse(self, layer, outname, shapetype, semimajorcol,
                       semiminorcol, orientcol, unitOfMeasure, defSemiMajor,
                       defSemiMinor, defOrientation):
        measureFactor = conversionToMeters(unitOfMeasure)

        fields = layer.fields()

        if shapetype == 0:
            self.outLayer = QgsVectorLayer(
                "Polygon?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        else:
            self.outLayer = QgsVectorLayer(
                "LineString?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        dp = self.outLayer.dataProvider()
        dp.addAttributes(fields)
        self.outLayer.updateFields()

        iter = layer.getFeatures()
        num_features = 0
        num_good = 0
        for feature in iter:
            num_features += 1
            try:
                if semimajorcol != -1:
                    semi_major = float(feature[semimajorcol])
                else:
                    semi_major = defSemiMajor
                if semiminorcol != -1:
                    semi_minor = float(feature[semiminorcol])
                else:
                    semi_minor = defSemiMinor
                if orientcol != -1:
                    orient = float(feature[orientcol])
                else:
                    orient = defOrientation
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                pts = geodesicEllipse(geod, pt.y(), pt.x(),
                                      semi_major * measureFactor,
                                      semi_minor * measureFactor, orient, 64)

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

                featureout = QgsFeature()
                featureout.setAttributes(feature.attributes())
                if shapetype == 0:
                    featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                else:
                    featureout.setGeometry(QgsGeometry.fromPolylineXY(pts))
                dp.addFeatures([featureout])
                num_good += 1
            except:
                # Just skip any lines that are badly formed
                #traceback.print_exc()
                pass
        self.outLayer.updateExtents()
        QgsProject.instance().addMapLayer(self.outLayer)
        self.iface.messageBar().pushMessage(
            "",
            "{} Ellipses created from {} records".format(
                num_good, num_features),
            level=Qgis.Info,
            duration=3)
Example #14
0
    def getPointsCaptured(self):
        TOMsMessageLog.logMessage(("In CreateRestrictionTool - getPointsCaptured"), level=Qgis.Info)

        # Check the number of points
        self.nrPoints = self.size()
        TOMsMessageLog.logMessage(("In CreateRestrictionTool - getPointsCaptured; Stopping: " + str(self.nrPoints)),
                                 level=Qgis.Info)

        self.sketchPoints = self.points()

        for point in self.sketchPoints:
            TOMsMessageLog.logMessage(("In CreateRestrictionTool - getPointsCaptured X:" + str(point.x()) + " Y: " + str(point.y())), level=Qgis.Info)

        # stop capture activity
        self.stopCapturing()

        if self.nrPoints > 0:

            # take points from the rubber band and copy them into the "feature"

            fields = self.layer.dataProvider().fields()
            feature = QgsFeature()
            feature.setFields(fields)

            TOMsMessageLog.logMessage(("In CreateRestrictionTool. getPointsCaptured, layerType: " + str(self.layer.geometryType())), level=Qgis.Info)

            if self.layer.geometryType() == 0:  # Point
                feature.setGeometry(QgsGeometry.fromPointXY(self.sketchPoints[0]))
            elif self.layer.geometryType() == 1:  # Line
                feature.setGeometry(QgsGeometry.fromPolylineXY(self.sketchPoints))
            elif self.layer.geometryType() == 2:  # Polygon
                feature.setGeometry(QgsGeometry.fromPolygonXY([self.sketchPoints]))
                #feature.setGeometry(QgsGeometry.fromPolygonXY(self.sketchPoints))
            else:
                TOMsMessageLog.logMessage(("In CreateRestrictionTool - no geometry type found"), level=Qgis.Info)
                return

            TOMsMessageLog.logMessage(("In Create - getPointsCaptured; geometry prepared; " + str(feature.geometry().asWkt())),
                                     level=Qgis.Info)

            if self.layer.name() == "ConstructionLines":
                self.layer.addFeature(feature)
            else:

                # set any geometry related attributes ...

                self.setDefaultFieldRestrictionDetails(feature, self.layer, QDate.currentDate())
                self.layer.addFeature(feature)  # TH (added for v3)
                #self.layer.reload()
                TOMsMessageLog.logMessage("In CreateRestrictionTool - getPointsCaptured. currRestrictionLayer: " + str(self.layer.name()),
                                         level=Qgis.Info)

                #newRestrictionID = str(uuid.uuid4())
                #feature[self.layer.fields().indexFromName("GeometryID")] = newRestrictionID


                dialog = self.iface.getFeatureForm(self.layer, feature)

                self.setupFieldRestrictionDialog(dialog, self.layer, feature)  # connects signals, etc

                self.inProcess = False
                dialog.show()

            pass
    def updateborn(self):
        if (self.lineEditNum.text() != ""):
            if (self.lineEditIndice.text() != ""):
                if (self.tableWidgetBornes.rowCount() >= 3):
                    print("'--INFO--' : Filter Passed Successfully")
                    cmbnature = self.comboBoxNature.currentText()
                    fieldnum = self.lineEditNum.text()
                    fieldindice = self.lineEditIndice.text()
                    typocomb = self.comboBoxType.currentText()
                    nbbornes = self.tableWidgetBornes.rowCount()
                    mapfield = self.comboBoxMap.currentText()
                    titreref = "" + cmbnature + fieldnum + fieldindice
                    conn = psycopg2.connect(
                        "dbname='postgres' user='******' password='******'")
                    print("'--INFO--' : Data Saved to Database")
                    try:
                        bornes = []
                        for x in range(0, nbbornes):
                            name = self.tableWidgetBornes.item(x, 0).text()
                            psx = self.tableWidgetBornes.item(x, 1).text()
                            psy = self.tableWidgetBornes.item(x, 2).text()
                            bornes.append(QgsPointXY(float(psx), float(psy)))
                            geometryborne = QgsGeometry.fromPointXY(
                                QgsPointXY(float(psx), float(psy))).asWkt()
                            try:
                                pt = QgsPointXY(float(psx), float(psy))
                                print("'--INFO--': name:" + name + " x:" +
                                      psx + " y:" + psy)
                                rb = QgsRubberBand(iface.mapCanvas(), True)
                                rb.reset(QgsWkbTypes.PointGeometry)
                                rb.addPoint(pt)
                                print("'--INFO--':  the born '" + name +
                                      "' was added.")
                            except:
                                print(
                                    "'--INFO--': You need to enter a number not text in X, Y Fields"
                                )

                            try:
                                sql = ("UPDATE public.bornes SET x = " + psx +
                                       ", y = " + psy +
                                       ", the_geom = ST_GeomFromText('" +
                                       geometryborne +
                                       "', 26191) WHERE titref = '" +
                                       titreref + "' AND name = '" + name +
                                       "';")
                                print(sql)
                                cur = conn.cursor()
                                cur.execute(sql)
                                conn.commit()
                            except:
                                print(
                                    "'--ERROR--': Error while sending querry")
                                self.ErrorLabel.setText("Error on Querry")
                    except:
                        print("'--INFO--': PLZ Fill all fields")
                        self.ErrorLabel.setText("Fields empty detected")

                    geometry = QgsGeometry.fromPolygonXY([bornes])
                    geometrypolygon = geometry.asWkt()
                    # thegeomshape = "ST_GeomFromText('"+geometry+"', 26191))

                    try:
                        sql = (
                            "UPDATE public.titres SET the_geom = ST_GeomFromText('"
                            + geometrypolygon + "', 26191) WHERE titref = '" +
                            titreref + "';")
                        print(sql)
                        cur = conn.cursor()
                        cur.execute(sql)
                        conn.commit()
                    except:
                        print("'--INFO--': Can''t edit titre")
                        self.ErrorLabel.setText("Can't Edit titre")
                else:
                    self.ErrorLabel.setText("Bornes < 3")
            else:
                self.ErrorLabel.setText("No Indice detected")
        else:
            self.ErrorLabel.setText("No Number detected")
Example #16
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]
                # 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 == 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 = []
                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(
                        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 = []
                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))
    def run(self):
        try:
            inputlayer = self.inputvectorlayer
            if inputlayer is None:
                self.error.emit(self.tr('No input layer defined'))
                self.finished.emit(False, None)
                return
            # Get and check the geometry type of the input layer
            geometryType = self.inputvectorlayer.geometryType()
            if not (geometryType == QgsWkbTypes.LineGeometry or
                    geometryType == QgsWkbTypes.PolygonGeometry):
                self.error.emit('Only line and polygon layers are supported!')
                self.finished.emit(False, None)
                return
            self.processed = 0
            self.percentage = 0
            if self.selectedfeaturesonly:
                self.feature_count = inputlayer.selectedFeatureCount()
            else:
                self.feature_count = inputlayer.featureCount()
            if self.feature_count == 0:
                self.error.emit("No features in layer")
                self.finished.emit(False, None)
                return
            self.increment = self.feature_count // 1000
            # Initialise the result list
            statistics = []
            # Initialise the bins for the over all result
            mybins = []
            for i in range(self.bins):
                mybins.append([0.0, 0])
            # Add the over all bins
            statistics.append(mybins)
            # Get the features (iterator)
            if self.selectedfeaturesonly:
                features = inputlayer.getSelectedFeatures()
#                features = inputlayer.selectedFeaturesIterator()
            else:
                features = inputlayer.getFeatures()
            # Create a list for the (possible) tile (Polygon)
            # geometries
            tilegeoms = []
            if self.tilelayer is not None:
                self.status.emit("Using tiles!")
                for tilefeat in self.tilelayer.getFeatures():
                    tilegeoms.append(tilefeat.geometry())
                # Initialise and add bins for all the tiles
                for i in range(len(tilegeoms)):
                    mybins = []
                    for j in range(self.bins):
                        mybins.append([0.0, 0])
                    statistics.append(mybins)
            # Go through the features
            for feat in features:
                # Allow user abort
                if self.abort is True:
                    break
                # Prepare for the histogram creation by extracting
                # line geometries (QgsGeometry) from the input layer

                # First we do all the lines of the layer.  Later we
                # will do the lines per tile
                # We use a list of line geometries to be able to
                # handle MultiPolylines and Polygons
                inputlines = []
                geom = feat.geometry()  # QgsGeometry
                if geometryType == QgsWkbTypes.LineGeometry:
                    # Lines!
                    if geom.isMultipart():
                        theparts = geom.constParts()
                        # QgsGeometryConstPartIterator
                        # Go through the parts of the multigeometry
                        for part in theparts:
                            # QgsAbstractGeometry - QgsLineString
                            partgeom = QgsGeometry.fromPolyline(part)
                            inputlines.append(partgeom)  # QgsGeometry
                    else:
                        inputlines.append(geom)
                # There are only two possibilites for geometry type, so
                # this elif: could be replaced with an else:
                elif geometryType == QgsWkbTypes.PolygonGeometry:
                    # Polygons!
                    # We use a list of polygon geometries to be able to
                    # handle MultiPolygons
                    inputpolygons = []
                    if geom.isMultipart():
                        # Multi polygon
                        multipoly = geom.asMultiPolygon()
                        for geompoly in multipoly:
                            # list of list of QgsPointXY
                            # abstract geometry -> QgsGeometry polygon
                            polygeometry = QgsGeometry.fromPolygonXY(geompoly)
                            inputpolygons.append(polygeometry)
                    else:
                        # Non-multi polygon
                        # Make sure it is a QgsGeometry polygon
                        singlegeom = geom.asPolygon()
                        polygeometry = QgsGeometry.fromPolygonXY(singlegeom)
                        inputpolygons.append(polygeometry)  # QgsGeometry
                    # Add the polygon rings
                    for polygon in inputpolygons:
                        # create a list of list of QgsPointXY
                        poly = polygon.asPolygon()
                        for ring in poly:
                            # list of QgsPointXY
                            # Create a QgsGeometry line
                            geometryring = QgsGeometry.fromPolylineXY(ring)
                            inputlines.append(geometryring)  # QgsGeometry
                else:
                    # We should never end up here
                    self.status.emit("Unexpected geometry type!")
                # We introduce a list of line geometries for the tiling
                tilelinecoll = [None] * (len(tilegeoms) + 1)
                # Use the first element to store all the input lines
                # (for the over all histogram)
                tilelinecoll[0] = inputlines
                # Clip the lines based on the tile layer
                if self.tilelayer is not None:
                    i = 1  # The first one is used for the complete dataset
                    for tile in tilegeoms:  # Go through the tiles
                        # Create a list for the lines in the tile
                        newlines = []
                        for linegeom in inputlines:
                            # QgsGeometry
                            # Clip
                            clipres = linegeom.intersection(tile)
                            if clipres.isEmpty():
                                continue
                            if clipres.isMultipart():
                                # MultiLineString
                                clipresparts = clipres.constParts()
                                for clipline in clipresparts:
                                  # Create a QgsGeometry line
                                  linegeom = QgsGeometry.fromPolyline(clipline)
                                  newlines.append(linegeom)  # QgsGeometry
                            else:
                                # ?
                                newlines.append(clipres)
                        tilelinecoll[i] = newlines
                        i = i + 1
                # Do calculations (line length and directions)
                j = 0  # Counter for the tiles
                for tilelines in tilelinecoll:  # Handling the tiles
                  for inputlinegeom in tilelines:  # Handling the lines
                    # QgsGeometry line - wkbType 2
                    if inputlinegeom is None:
                        continue
                    numvert = 0
                    for v in inputlinegeom.vertices():
                       numvert = numvert + 1
                    if numvert == 0:
                        continue
                    if numvert < 2:
                        self.status.emit("Less than two vertices!")
                        continue
                    # Go through all the segments of this line
                    thispoint = inputlinegeom.vertexAt(0)  # QgsPoint
                    first = True
                    for v in inputlinegeom.vertices():
                        if first:
                            first = False
                            continue
                        nextpoint = v
                        linelength = sqrt(thispoint.distanceSquared(nextpoint))
                        # Find the angle of the line segment
                        lineangle = thispoint.azimuth(nextpoint)
                        if lineangle < 0:
                            lineangle = 360 + lineangle
                        if self.directionneutral:
                            if lineangle >= 180.0:
                                lineangle = lineangle - 180
                        # Find the bin
                        if lineangle > self.offsetangle:
                            fitbin = (int((lineangle - self.offsetangle) /
                                      self.binsize) % self.bins)
                        else:
                            fitbin = (int((360 + lineangle -
                                           self.offsetangle) / self.binsize) %
                                      self.bins)
                        # Have to handle special case to keep index in range?
                        if fitbin == self.bins:
                            self.status.emit("fitbin == self.bins")
                            fitbin = 0
                        # Add to the length of the bin of this tile (j)
                        statistics[j][fitbin][0] = (statistics[j][fitbin][0] +
                                                    linelength)
                        # Add to the number of line segments in the bin
                        statistics[j][fitbin][1] = (statistics[j][fitbin][1] +
                                                    1)
                        thispoint = nextpoint  # advance to the next point
                  j = j + 1  # Next tile
                self.calculate_progress()
        except Exception as e:
            self.status.emit("Exception occurred - " + str())
            self.error.emit(str(e))
            self.finished.emit(False, None)
        else:
            if self.abort:
                self.status.emit("Aborted")
                self.finished.emit(False, None)
            else:
                self.status.emit("Completed")
                self.finished.emit(True, statistics)
    def processPoly(self, layer, outname, shapetype, sidescol, anglecol,
                    distcol, sides, angle, defaultDist, unitOfDist):
        measureFactor = conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        fields = layer.fields()

        if shapetype == 0:
            outLayer = QgsVectorLayer(
                "Polygon?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        else:
            outLayer = QgsVectorLayer(
                "LineString?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        dp = outLayer.dataProvider()
        dp.addAttributes(fields)
        outLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            try:
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                if sidescol != -1:
                    s = int(feature[sidescol])
                else:
                    s = sides
                if anglecol != -1:
                    startangle = float(feature[anglecol])
                else:
                    startangle = angle
                if distcol != -1:
                    d = float(feature[distcol]) * measureFactor
                else:
                    d = defaultDist
                pts = []
                i = s
                while i >= 0:
                    a = (i * 360.0 / s) + startangle
                    i -= 1
                    g = geod.Direct(pt.y(), pt.x(), a, d,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))

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

                featureout = QgsFeature()
                if shapetype == 0:
                    featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                else:
                    featureout.setGeometry(QgsGeometry.fromPolylineXY(pts))
                featureout.setAttributes(feature.attributes())
                dp.addFeatures([featureout])
            except:
                pass

        outLayer.updateExtents()
        QgsProject.instance().addMapLayer(outLayer)
    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]
                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 = [(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(
                        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 = [(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))
Example #20
0
 def addPolygonsToMap(self, polygons):
     if not QgsProject.instance().mapLayersByName(
             'Location Lab - catchments'):
         vl = QgsVectorLayer('Polygon?crs=EPSG:4326',
                             'Location Lab - catchments', 'memory')
         pr = vl.dataProvider()
         vl.startEditing()
         pr.addAttributes([
             QgsField('id', QVariant.Int),
             QgsField(self.tr('provider'), QVariant.String),
             QgsField(self.tr('mode'), QVariant.String),
             QgsField(self.tr('value'), QVariant.Int),
             QgsField(self.tr('units'), QVariant.String),
             QgsField(self.tr('lat'), QVariant.Double),
             QgsField(self.tr('lon'), QVariant.Double),
             QgsField('params', QVariant.String)
         ])
         vl.commitChanges()
         QgsProject.instance().addMapLayer(vl)
     vl = QgsProject.instance().mapLayersByName(
         'Location Lab - catchments')[0]
     pr = vl.dataProvider()
     next_id = len(vl.allFeatureIds()) + 1
     id_field = self.fieldsComboBox.currentField()
     if id_field:
         layer = self.layerComboBox.currentLayer()
         new_ids = [
             feature.attribute(id_field)
             for feature in list(layer.getFeatures())
         ]
     for index, p in enumerate(polygons):
         feature = QgsFeature()
         points = []
         if p['source'] == 'HERE' or p['source'] == 'OpenRouteService':
             coordinates = [c.split(',') for c in p['coordinates']]
             for xy in coordinates:
                 points.append(QgsPointXY(float(xy[1]), float(xy[0])))
         feature = QgsFeature()
         feature.setGeometry(QgsGeometry.fromPolygonXY([points]))
         lat, lon = p['coords'].split(',')
         for key in ['key', 'url', 'coordinates',
                     'start']:  #unnecessary params
             if key in p.keys():
                 p.pop(key)
         feature.setAttributes([
             next_id if not id_field else new_ids[index],
             self.providersComboBox.currentText(),
             self.modesComboBox.currentText().lower(),
             self.valueSpinBox.value(),
             self.unitsComboBox.currentText(),
             float(lat),
             float(lon),
             str(p)
         ])
         pr.addFeatures([feature])
         next_id += 1
     vl.updateExtents()
     self.iface.mapCanvas().setExtent(
         QgsCoordinateTransform(
             vl.crs(),
             self.iface.mapCanvas().mapSettings().destinationCrs(),
             QgsProject().instance()).transform(vl.extent()))
     self.iface.mapCanvas().refresh()
Example #21
0
 def get_transformed_polygon(self, feature, distance_area, xform):
     """Returns transformd polygon geometry"""
     # TODO: distance_area and xform should probably be class variables
     points = feature.geometry().asPolygon()
     transformed = [self.transform_point(xform, point) for point in points[0]]
     return QgsGeometry.fromPolygonXY([transformed])
Example #22
0
 def _ignitePerimeters(self, layer):
     perimeters = self._perimeter_layer.getFeatures()
     perimeters_features = [
         f for f in perimeters
         if f.attributes()[1] == self._tnow.strftime('%Y-%m-%dT%H:%M:%S')
     ]
     perimeters = list()
     for perimeter_feature in perimeters_features:
         new_perimeter = list()
         geom = perimeter_feature.geometry().asPolygon()
         points = list()
         for pt in geom[0]:
             feat = QgsFeature()
             feat.setGeometry(
                 QgsGeometry.fromPointXY(QgsPointXY(pt.x(), pt.y())))
             ip = IgnitionPoint(feat, pt.x(), pt.y(),
                                self._tnow.strftime('%Y-%m-%dT%H:%M:%S'))
             points.append(ip)
         self._assignFuel(points)
         new_points = self._propagatePerimeter(points[-2::-1])
         new_perimeter.append(
             [QgsPointXY(pt[0], pt[1]) for pt in new_points])
         if len(geom) > 1:
             for i in range(1, len(geom)):
                 points = list()
                 for pt in geom[i]:
                     feat = QgsFeature()
                     feat.setGeometry(
                         QgsGeometry.fromPointXY(QgsPointXY(pt.x(),
                                                            pt.y())))
                     ip = IgnitionPoint(
                         feat, pt.x(), pt.y(),
                         self._tnow.strftime('%Y-%m-%dT%H:%M:%S'))
                     points.append(ip)
                 self._assignFuel(points)
                 new_points = self._propagatePerimeter(points[-2::-1])
                 new_perimeter.append(
                     [[QgsPointXY(pt[0], pt[1]) for pt in new_points],
                      geom[i]])
         perimeters.append(new_perimeter)
     for perimeter in perimeters:
         # Create a line layer to calculate rings
         layer_in = self._createMemoryLayer(
             'Polygon',
             QgsProject.instance().crs().authid(), 'outer_perimeter')
         self._addPerimeterToLayer(layer_in, [perimeter[0]])
         params = {'INPUT': layer_in, 'OUTPUT': 'memory:'}
         feedback = QgsProcessingFeedback()
         result = processing.run('native:fixgeometries',
                                 params,
                                 feedback=feedback,
                                 is_child_algorithm=False)
         fixed_layer = result['OUTPUT']
         params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:'}
         feedback = QgsProcessingFeedback()
         result = processing.run('native:polygonstolines',
                                 params,
                                 feedback=feedback,
                                 is_child_algorithm=False)
         line_layer = result['OUTPUT']
         params = {
             'INPUT': line_layer,
             'LINES': line_layer,
             'OUTPUT': 'memory:'
         }
         feedback = QgsProcessingFeedback()
         result = processing.run('native:splitwithlines',
                                 params,
                                 feedback=feedback,
                                 is_child_algorithm=False)
         split_layer = result['OUTPUT']
         params = {'INPUT': split_layer, 'OUTPUT': 'memory:'}
         feedback = QgsProcessingFeedback()
         result = processing.run('qgis:linestopolygons',
                                 params,
                                 feedback=feedback,
                                 is_child_algorithm=False)
         polygon_layer = result['OUTPUT']
         params = {'INPUT': polygon_layer, 'OUTPUT': 'memory:'}
         feedback = QgsProcessingFeedback()
         result = processing.run('native:multiparttosingleparts',
                                 params,
                                 feedback=feedback,
                                 is_child_algorithm=False)
         correct_plygons = result['OUTPUT']
         island_layer = None
         if correct_plygons.featureCount() > 1:
             island_layer = self._findRing(correct_plygons)
         #params = {'INPUT': polygon_layer, 'OUTPUT': 'memory:'}
         #feedback = QgsProcessingFeedback()
         #result = processing.run('native:dissolve', params, feedback=feedback, is_child_algorithm=False)
         #dissolved_layer = result['OUTPUT']
         #if island_layer is None:
         #    params = {'INPUT': polygon_layer, 'OUTPUT': 'memory:'}
         #else:
         #    params = {'INPUT': island_layer, 'OUTPUT': 'memory:'}
         #feedback = QgsProcessingFeedback()
         #result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False)
         #correct_plygons = result['OUTPUT']
         if island_layer is None:
             rings_layer = correct_plygons
         else:
             rings_layer = island_layer
         feats = [f for f in rings_layer.getFeatures()]
         elements = feats[0].geometry().asPolygon()
         new_perimeter = list()
         for element in elements:
             new_perimeter.append(
                 [QgsPointXY(pt.x(), pt.y()) for pt in element])
         del (layer_in)
         del (fixed_layer)
         del (line_layer)
         del (split_layer)
         del (polygon_layer)
         if not (island_layer is None):
             del (island_layer)
         del (correct_plygons)
         if len(perimeter) > 1:
             for i in range(1, len(perimeter)):
                 # Create layer fromprevious perimeter
                 geom = perimeter[i][1]
                 feature = QgsFeature()
                 feature.setGeometry(QgsGeometry.fromPolygonXY([geom]))
                 previous_ring = self._createMemoryLayer(
                     'Polygon',
                     QgsProject.instance().crs().authid(), 'previous_ring')
                 previous_ring.dataProvider().addFeatures([feature])
                 actual_ring = self._createMemoryLayer(
                     'Polygon',
                     QgsProject.instance().crs().authid(), 'actual_ring')
                 self._addPerimeterToLayer(actual_ring, [perimeter[i][0]])
                 params = {'INPUT': actual_ring, 'OUTPUT': 'memory:'}
                 feedback = QgsProcessingFeedback()
                 result = processing.run('native:fixgeometries',
                                         params,
                                         feedback=feedback,
                                         is_child_algorithm=False)
                 fixed_layer = result['OUTPUT']
                 params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:'}
                 feedback = QgsProcessingFeedback()
                 result = processing.run('native:polygonstolines',
                                         params,
                                         feedback=feedback,
                                         is_child_algorithm=False)
                 line_layer = result['OUTPUT']
                 params = {
                     'INPUT': line_layer,
                     'LINES': line_layer,
                     'OUTPUT': 'memory:'
                 }
                 feedback = QgsProcessingFeedback()
                 result = processing.run('native:splitwithlines',
                                         params,
                                         feedback=feedback,
                                         is_child_algorithm=False)
                 split_layer = result['OUTPUT']
                 params = {'INPUT': split_layer, 'OUTPUT': 'memory:'}
                 feedback = QgsProcessingFeedback()
                 result = processing.run('qgis:linestopolygons',
                                         params,
                                         feedback=feedback,
                                         is_child_algorithm=False)
                 polygon_layer = result['OUTPUT']
                 params = {
                     'INPUT': polygon_layer,
                     'PREDICATE': [6],
                     'INTERSECT': previous_ring,
                     'OUTPUT': 'memory:'
                 }
                 feedback = QgsProcessingFeedback()
                 result = processing.run('native:extractbylocation',
                                         params,
                                         feedback=feedback,
                                         is_child_algorithm=False)
                 rings_inside = result['OUTPUT']
                 params = {'INPUT': rings_inside, 'OUTPUT': 'memory:'}
                 feedback = QgsProcessingFeedback()
                 result = processing.run('native:multiparttosingleparts',
                                         params,
                                         feedback=feedback,
                                         is_child_algorithm=False)
                 correct_rings = result['OUTPUT']
                 for feature in correct_rings.getFeatures():
                     geom = feature.geometry().asPolygon()
                     for elem in geom:
                         new_perimeter.append(
                             [QgsPointXY(pt.x(), pt.y()) for pt in elem])
                 del (previous_ring)
                 del (actual_ring)
                 del (fixed_layer)
                 del (line_layer)
                 del (split_layer)
                 del (rings_inside)
                 del (correct_rings)
         self._addPerimeterToLayer(layer, new_perimeter)
Example #23
0
def UpdateFootPrintData(packet, cornerPointUL, cornerPointUR, cornerPointLR,
                        cornerPointLL, ele):
    """ Update Footprint Values """
    global crtSensorSrc, groupName
    imgSS = packet.ImageSourceSensor

    footprintLyr = selectLayerByName(Footprint_lyr, groupName)

    try:
        if all(v is not None for v in [
                footprintLyr,
                cornerPointUL,
                cornerPointUR,
                cornerPointLR,
                cornerPointLL,
        ]) and all(v >= 2 for v in [
                len(cornerPointUL),
                len(cornerPointUR),
                len(cornerPointLR),
                len(cornerPointLL),
        ]):
            if imgSS != crtSensorSrc:
                SetDefaultFootprintStyle(footprintLyr, imgSS)
                crtSensorSrc = imgSS

            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:
                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]),
                    ]])
                })

            CommonLayer(footprintLyr)
            # 3D Style
            if ele:
                SetDefaultFootprint3DStyle(footprintLyr)

    except Exception as e:
        qgsu.showUserAndLogMessage(
            QCoreApplication.translate("QgsFmvLayers",
                                       "Failed Update FootPrint Layer! : "),
            str(e),
        )
Example #24
0
 def _addPerimeterToLayer(self, layer, perimeter):
     feat = QgsFeature()
     geom = QgsGeometry.fromPolygonXY(perimeter)
     feat.setGeometry(geom)
     (res, outFeats) = layer.dataProvider().addFeatures([feat])
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer, context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        outerCol = self.parameterAsString(parameters, self.PrmOuterRadiusField, context)
        innerCol = self.parameterAsString(parameters, self.PrmInnerRadiusField, context)
        starPointsCol = self.parameterAsString(parameters, self.PrmStarPointsField, context)
        startAngleCol = self.parameterAsString(parameters, self.PrmStartingAngleField, context)
        outerRadius = self.parameterAsDouble(parameters, self.PrmDefaultOuterRadius, context)
        innerRadius = self.parameterAsDouble(parameters, self.PrmDefaultInnerRadius, context)
        startAngle = self.parameterAsDouble(parameters, self.PrmDefaultStartingAngle, context)
        numPoints = self.parameterAsInt(parameters, self.PrmDefaultStarPoints, context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context)
        
        measureFactor = conversionToMeters(units)
        innerRadius *= measureFactor
        outerRadius *= measureFactor

        srcCRS = source.sourceCrs()
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                self.PrmOutputLayer, context, source.fields(),
                QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink, dest_id) = self.parameterAsSink(parameters,
                self.PrmOutputLayer, context, source.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
        
        half = (360.0 / numPoints) / 2.0

        numbad = 0
        iterator = source.getFeatures()
        for cnt, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                pts = []
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                if srcCRS != epsg4326:
                    pt = geomTo4326.transform(pt.x(), pt.y())
                    
                if outerCol:
                    oradius = float(feature[outerCol]) * measureFactor
                else:
                    oradius = outerRadius
                if innerCol:
                    iradius = float(feature[innerCol]) * measureFactor
                else:
                    iradius = innerRadius
                if startAngleCol:
                    sangle = float(feature[startAngleCol])
                else:
                    sangle = startAngle
                if starPointsCol:
                    spoints = float(feature[starPointsCol])
                    shalf = (360.0 / spoints) / 2.0
                else:
                    spoints = numPoints
                    shalf = half
                    
                i = spoints - 1
                while i >= 0:
                    i -= 1
                    angle = (i * 360.0 / spoints) + sangle
                    g = geod.Direct(pt.y(), pt.x(), angle, oradius, Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    g = geod.Direct(pt.y(), pt.x(), angle-shalf, iradius, Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    
                # 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))
                f.setAttributes(feature.attributes())
                sink.addFeature(f)
            except:
                '''s = traceback.format_exc()
                feedback.pushInfo(s)'''
                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}
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shape_type = self.parameterAsInt(parameters, self.PrmShapeType,
                                         context)
        semi_major_col = self.parameterAsString(parameters,
                                                self.PrmSemiMajorAxisField,
                                                context)
        semi_minor_col = self.parameterAsString(parameters,
                                                self.PrmSemiMinorAxisField,
                                                context)
        orientation_col = self.parameterAsString(parameters,
                                                 self.PrmOrientationField,
                                                 context)
        default_semi_major = self.parameterAsDouble(
            parameters, self.PrmDefaultSemiMajorAxis, context)
        default_semi_minor = self.parameterAsDouble(
            parameters, self.PrmDefaultSemiMinorAxis, context)
        def_orientation = self.parameterAsDouble(parameters,
                                                 self.PrmDefaultOrientation,
                                                 context)
        segments = self.parameterAsInt(parameters, self.PrmDrawingSegments,
                                       context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                    context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        measure_factor = conversionToMeters(units)

        default_semi_major *= measure_factor
        default_semi_minor *= measure_factor

        src_crs = 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 shape_type == 0:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, fields,
                                             QgsWkbTypes.Polygon, src_crs)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, fields,
                                             QgsWkbTypes.LineString, src_crs)

        if src_crs != epsg4326:
            geom_to_4326 = QgsCoordinateTransform(src_crs, epsg4326,
                                                  QgsProject.instance())
            to_sink_crs = QgsCoordinateTransform(epsg4326, src_crs,
                                                 QgsProject.instance())

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

        iterator = source.getFeatures()
        num_bad = 0
        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 src_crs != epsg4326:
                    pt = geom_to_4326.transform(pt.x(), pt.y())
                lat = pt.y()
                lon = pt.x()
                if semi_major_col:
                    sma = float(feature[semi_major_col]) * measure_factor
                else:
                    sma = default_semi_major
                if semi_minor_col:
                    smi = float(feature[semi_minor_col]) * measure_factor
                else:
                    smi = default_semi_minor
                if orientation_col:
                    orient = float(feature[orientation_col])
                else:
                    orient = def_orientation

                pts = geodesicEllipse(geod, lat, lon, sma, smi, orient,
                                      segments)

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

                f = QgsFeature()
                if shape_type == 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:
                num_bad += 1
                '''s = traceback.format_exc()
                feedback.pushInfo(s)'''

            feedback.setProgress(int(cnt * total))

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

        return {self.PrmOutputLayer: dest_id}
    def processPie(self, layer, outname, shapetype, azimuthMode, startanglecol,
                   endanglecol, distcol, unitOfDist, startangle, endangle,
                   defaultDist, segments):
        measureFactor = conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        arcPtSpacing = 360.0 / segments

        fields = layer.fields()

        if shapetype == 0:
            outLayer = QgsVectorLayer(
                "Polygon?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        else:
            outLayer = QgsVectorLayer(
                "LineString?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        dp = outLayer.dataProvider()
        dp.addAttributes(fields)
        outLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            try:
                pts = []
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                pts.append(pt)
                if startanglecol == -1:
                    sangle = startangle
                else:
                    sangle = float(feature[startanglecol])
                if endanglecol == -1:
                    eangle = endangle
                else:
                    eangle = float(feature[endanglecol])
                if azimuthMode == 1:
                    width = abs(eangle) / 2.0
                    eangle = sangle + width
                    sangle -= width
                if distcol == -1:
                    dist = defaultDist
                else:
                    dist = float(feature[distcol]) * measureFactor

                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 += arcPtSpacing  # 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)

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

                featureout = QgsFeature()
                if shapetype == 0:
                    featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                else:
                    featureout.setGeometry(QgsGeometry.fromPolylineXY(pts))
                featureout.setAttributes(feature.attributes())
                dp.addFeatures([featureout])
            except:
                pass

        outLayer.updateExtents()
        QgsProject.instance().addMapLayer(outLayer)
Example #28
0
    def testAreaMeasureAndUnits(self):
        """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the
           calculated areas and units are always consistent
        """

        da = QgsDistanceArea()
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")

        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0),
            ]]
        )

        # We check both the measured area AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
                (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))

        da.setEllipsoid("WGS84")
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        # should always be in Meters Squared
        self.assertAlmostEqual(area, 37416879192.9, delta=0.1)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles)
        self.assertAlmostEqual(area, 14446.7378, delta=0.001)

        # now try with a source CRS which is in feet
        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000)
            ]]
        )
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")
        # measurement should be in square feet
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 2000000, delta=0.001)
        self.assertEqual(units, QgsUnitTypes.AreaSquareFeet)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 222222.2222, delta=0.001)

        da.setEllipsoid("WGS84")
        # now should be in Square Meters again
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 184149.37, delta=1.0)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 220240.8172549, delta=1.0)
    def processDonut(self, layer, outname, shapetype, innerCol, outerCol,
                     defInnerRadius, defOuterRadius, units, segments):
        measureFactor = conversionToMeters(units)

        defInnerRadius *= measureFactor
        defOuterRadius *= measureFactor

        ptSpacing = 360.0 / segments

        fields = layer.fields()

        if shapetype == 0:
            outLayer = QgsVectorLayer(
                "Polygon?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        else:
            outLayer = QgsVectorLayer(
                "MultiLineString?crs={}".format(self.outputCRS.authid()),
                outname, "memory")
        dp = outLayer.dataProvider()
        dp.addAttributes(fields)
        outLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            try:
                ptsi = []
                ptso = []
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                lat = pt.y()
                lon = pt.x()
                angle = 0
                while angle < 360:
                    if innerCol == -1:
                        iRadius = defInnerRadius
                    else:
                        iRadius = float(feature[innerCol]) * measureFactor
                    if outerCol == -1:
                        oRadius = defOuterRadius
                    else:
                        oRadius = float(feature[outerCol]) * measureFactor
                    if iRadius != 0:
                        g = geod.Direct(lat, lon, angle, iRadius,
                                        Geodesic.LATITUDE | Geodesic.LONGITUDE)
                        ptsi.append(QgsPointXY(g['lon2'], g['lat2']))
                    g = geod.Direct(lat, lon, angle, oRadius,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    ptso.append(QgsPointXY(g['lon2'], g['lat2']))
                    angle += ptSpacing
                if iRadius != 0:
                    ptsi.append(ptsi[0])
                ptso.append(ptso[0])

                # If the Output crs is not 4326 transform the points to the proper crs
                if self.outputCRS != epsg4326:
                    if iRadius != 0:
                        for x, ptout in enumerate(ptsi):
                            ptsi[x] = self.transformOut.transform(ptout)
                    for x, ptout in enumerate(ptso):
                        ptso[x] = self.transformOut.transform(ptout)

                featureout = QgsFeature()
                if shapetype == 0:
                    if iRadius == 0:
                        featureout.setGeometry(
                            QgsGeometry.fromPolygonXY([ptso]))
                    else:
                        featureout.setGeometry(
                            QgsGeometry.fromPolygonXY([ptso, ptsi]))
                else:
                    if iRadius == 0:
                        featureout.setGeometry(
                            QgsGeometry.fromMultiPolylineXY([ptso]))
                    else:
                        featureout.setGeometry(
                            QgsGeometry.fromMultiPolylineXY([ptso, ptsi]))
                featureout.setAttributes(feature.attributes())
                dp.addFeatures([featureout])
            except:
                pass

        outLayer.updateExtents()
        QgsProject.instance().addMapLayer(outLayer)
Example #30
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        radius = self.parameterAsDouble(parameters, self.PrmRadius, context)
        startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle,
                                            context)
        k = self.parameterAsInt(parameters, self.PrmPetals, context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                    context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        measureFactor = conversionToMeters(units)
        radius *= measureFactor

        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())

        dist = []
        if k == 1:
            dist.append(0.0)
        step = 1
        angle = -90.0 + step
        while angle < 90.0:
            a = math.radians(angle)
            r = math.cos(a)
            dist.append(r)
            angle += step
        cnt = len(dist)

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

        iterator = source.getFeatures()
        for item, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            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())
            arange = 360.0 / k
            angle = -arange / 2.0
            astep = arange / cnt
            for i in range(k):
                aoffset = arange * (k - 1)
                index = 0
                while index < cnt:
                    r = dist[index] * radius
                    g = geod.Direct(pt.y(), pt.x(),
                                    angle + aoffset + startAngle, r,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    angle += astep
                    index += 1
            # repeat the very first point to close the polygon
            pts.append(pts[0])

            # 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)

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

        return {self.PrmOutputLayer: dest_id}
    def processRose(self, layer, outname, shapetype, startAngle, k, radius,
                    unitOfDist):
        measureFactor = conversionToMeters(unitOfDist)

        radius *= measureFactor
        fields = layer.fields()

        if shapetype == 0:
            outLayer = QgsVectorLayer(
                "Polygon?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        else:
            outLayer = QgsVectorLayer(
                "LineString?crs={}".format(self.outputCRS.authid()), outname,
                "memory")
        dp = outLayer.dataProvider()
        dp.addAttributes(fields)
        outLayer.updateFields()

        iter = layer.getFeatures()
        dist = []
        if k == 1:
            dist.append(0.0)
        step = 1
        angle = -90.0 + step
        while angle < 90.0:
            a = math.radians(angle)
            r = math.cos(a)
            dist.append(r)
            angle += step
        cnt = len(dist)

        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            arange = 360.0 / k
            angle = -arange / 2.0
            astep = arange / cnt
            for i in range(k):
                aoffset = arange * (k - 1)
                index = 0
                while index < cnt:
                    r = dist[index] * radius
                    g = geod.Direct(pt.y(), pt.x(),
                                    angle + aoffset + startAngle, r,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    angle += astep
                    index += 1
            # repeat the very first point to close the polygon
            pts.append(pts[0])

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

            featureout = QgsFeature()
            if shapetype == 0:
                featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            else:
                featureout.setGeometry(QgsGeometry.fromPolylineXY(pts))
            featureout.setAttributes(feature.attributes())
            dp.addFeatures([featureout])

        outLayer.updateExtents()
        QgsProject.instance().addMapLayer(outLayer)
Example #32
0
    def processAlgorithm(self, parameters, context, feedback):

        # inputs
        rasters = self.parameterAsLayerList(parameters, self.RASTERLIST,
                                            context)
        if rasters is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.RASTERLIST))

        reamostragem = self.parameterAsEnum(parameters, self.RESAMPLING,
                                            context)
        reamostragem = ['nearest', 'bilinear', 'bicubic'][reamostragem]

        sobrep = self.parameterAsEnum(parameters, self.OVERLAP, context)

        muda_res = self.parameterAsBool(parameters, self.CHANGERESOLUTION,
                                        context)

        resolucao = self.parameterAsDouble(parameters, self.RESOLUTION,
                                           context)

        valor_nulo = self.parameterAsDouble(parameters, self.NULLVALUE,
                                            context)

        moldura = self.parameterAsDouble(parameters, self.CLIP, context)

        if moldura:
            vlayer = self.parameterAsVectorLayer(parameters, self.FRAME,
                                                 context)
            if vlayer is None:
                raise QgsProcessingException(
                    self.invalidSourceError(parameters, self.FRAME))

        # output

        Output = self.parameterAsFileOutput(parameters, self.MOSAIC, context)

        Carregar = self.parameterAsBool(parameters, self.OPEN, context)

        lista = []
        for raster_lyr in rasters:
            lista += [raster_lyr.dataProvider().dataSourceUri()]
        if len(lista) < 1:
            raise QgsProcessingException(
                self.tr('At least one raster must be selected!',
                        'Pelo menos um raster deve ser selecionado!'))
        if len(lista) == 1:
            sobrep = 0  # apenas um raster (sem sobreposicao)

        # Gerar geometria para cada raster
        geoms = []
        SRC = []
        n_bands = []
        GDT = []
        nulos = []
        XRES, YRES = [], []
        for item in lista:
            image = gdal.Open(item)
            SRC += [QgsCoordinateReferenceSystem(image.GetProjection())]  # wkt
            ulx, xres, xskew, uly, yskew, yres = image.GetGeoTransform()
            cols = image.RasterXSize
            rows = image.RasterYSize
            n_bands += [image.RasterCount]
            GDT += [image.GetRasterBand(1).DataType]
            nulos += [image.GetRasterBand(1).GetNoDataValue()]
            XRES += [xres]
            YRES += [yres]
            image = None  # Close image
            # Creating BBox
            coord = [[
                QgsPointXY(ulx, uly),
                QgsPointXY(ulx + cols * xres, uly),
                QgsPointXY(ulx + cols * xres, uly + rows * yres),
                QgsPointXY(ulx, uly + rows * yres),
                QgsPointXY(ulx, uly)
            ]]
            geom = QgsGeometry.fromPolygonXY(coord)
            geoms += [geom]

        ## Validar dados de entrada
        # Mesmo numero de bandas
        if not n_bands.count(n_bands[0]) == len(n_bands):
            raise QgsProcessingException(
                self.tr('The images must have the same number of bands!',
                        'As imagens devem ter o mesmo número de bandas!'))
        # Mesmo SRC
        if not SRC.count(SRC[0]) == len(SRC):
            raise QgsProcessingException(
                self.tr('The images must have the same CRS!',
                        'As imagens devem ter o mesmo SRC!'))
        # Mesmo GDT
        if not GDT.count(GDT[0]) == len(GDT):
            raise QgsProcessingException(
                self.tr('The images must have the same data type!',
                        'As imagens devem ter o tipo de dado!'))
        # Mesmo valor nulo
        if not nulos.count(nulos[0]) == len(nulos):
            raise QgsProcessingException(
                self.tr(
                    'The images must have the same definied null value!',
                    'As imagens devem ter o mesmo valor para definir pixel nulo!'
                ))

        # Dados para o raster de saída
        prj = SRC[0].toWkt()
        n_bands = n_bands[0]
        GDT = GDT[0]
        xres = np.mean(XRES)
        yres = np.mean(YRES)
        NULO = valor_nulo
        if valor_nulo == -1:
            valor_nulo = nulos[0] if nulos[0] is not None else 0

        if moldura:  # Pegar extensão X e Y da moldura
            # SRC da moldura deve ser o mesmo dos raster
            if vlayer.sourceCrs() != QgsCoordinateReferenceSystem(prj):
                raise QgsProcessingException(
                    self.tr(
                        "The frame's CRS must be iqual to the rasters' CRS!",
                        'O SRC da moldura deve ser igual ao SRC dos rasters!'))
            for feat in vlayer.getFeatures():
                moldura_geom = feat.geometry()
                break
            moldura_rect = moldura_geom.boundingBox()
            y_min = moldura_rect.yMinimum()
            y_max = moldura_rect.yMaximum()
            x_min = moldura_rect.xMinimum()
            x_max = moldura_rect.xMaximum()
        else:  # Mesclar geometrias e obter a extensão
            new_geom = QgsGeometry()
            new_geom = new_geom.unaryUnion(geoms)
            extensao = new_geom.boundingBox()
            # Coodenadas máxima e mínima da extensão
            y_min = extensao.yMinimum()
            y_max = extensao.yMaximum()
            x_min = extensao.xMinimum()
            x_max = extensao.xMaximum()

        # Transformar resolucao de metros para graus, se o SRC for Geográfico
        src_qgis = QgsCoordinateReferenceSystem(prj)
        if src_qgis.isGeographic():
            EPSG = int(src_qgis.authid().split(':')[-1])
            proj_crs = CRS.from_epsg(EPSG)
            a = proj_crs.ellipsoid.semi_major_metre
            f = 1 / proj_crs.ellipsoid.inverse_flattening
            e2 = f * (2 - f)
            N = a / np.sqrt(1 - e2 * (np.sin(
                (y_min + y_max) / 2))**2)  # Raio de curvatura 1º vertical
            M = a * (1 - e2) / (1 - e2 * (np.sin((y_min + y_max) / 2))**2)**(
                3 / 2.)  # Raio de curvatura meridiana
            R = np.sqrt(M * N)  # Raio médio de Gauss
            theta = resolucao / R
            resolucao = np.degrees(theta)  # Radianos para graus

        # Definir n_col, n_lin e resolucao
        if moldura:
            if muda_res:
                n_lin = round((y_max - y_min) / abs(resolucao))
                n_col = round((x_max - x_min) / abs(resolucao))
            else:
                n_lin = round((y_max - y_min) / abs(yres))
                n_col = round((x_max - x_min) / abs(xres))
            xres = (x_max - x_min) / n_col
            yres = -(y_max - y_min) / n_lin
        else:
            if muda_res:
                n_lin = round((y_max - y_min) / abs(resolucao))
                n_col = round((x_max - x_min) / abs(resolucao))
                xres = resolucao
                yres = -resolucao
            else:
                n_lin = round((y_max - y_min) / abs(yres))
                n_col = round((x_max - x_min) / abs(xres))
                xres = (x_max - x_min) / n_col
                yres = -(y_max - y_min) / n_lin

        feedback.pushInfo(
            self.tr('Resolution: ', 'Resolução: ') + str(n_lin) + 'x' +
            str(n_col))
        # Geotransform do Mosaico
        ulx = x_min
        uly = y_max
        xskew, yskew = 0, 0
        geotransform = [ulx, xres, xskew, uly, yskew, yres]
        origem = (ulx, uly)
        resol_X = abs(xres)
        resol_Y = abs(yres)
        # Numeração das Imagens
        valores = list(range(1, len(lista) + 1))

        # Definição de áreas de varredura
        feedback.pushInfo(
            self.tr('Defining mosaic filling areas...',
                    'Definindo áreas de preenchimento do mosaico...'))

        # Gerar combinações dos Rasters
        if sobrep != 0:
            combs = []
            feedback.pushInfo(
                self.tr('Creating combinations...', 'Gerando combinações...'))
            for k in range(1, 5):
                combs += list(combinations(valores, k))
                if feedback.isCanceled():
                    break
            # Armazenar geometrias exclusivas de cada combinação
            classes = {}
            feedback.pushInfo(
                self.tr('Indentifying combinations...',
                        'Identificando combinações...'))
            Percent = 100.0 / (len(combs))
            current = 0

            for comb in combs:
                if len(comb) == 1:
                    geom1 = geoms[comb[0] - 1]
                    lista_outras = []
                    for geom in geoms:
                        if geom1 != geom:
                            lista_outras += [geom]
                    outras = QgsGeometry()
                    outras = outras.unaryUnion(lista_outras)
                    diferença = geom1.difference(outras)
                    if not diferença.isEmpty():
                        classes[comb] = {'geom': diferença}
                elif len(comb) < len(valores):
                    intersecao = geoms[comb[0] - 1]
                    sentinela = True
                    for ind in comb[1:]:
                        geom = geoms[ind - 1]
                        if geom.intersects(intersecao):
                            intersecao = intersecao.intersection(geom)
                        else:
                            sentinela = False
                            continue
                    lista_outras = []
                    for valor in valores:
                        if valor not in comb:
                            lista_outras += [geoms[valor - 1]]
                    outras = QgsGeometry()
                    outras = outras.unaryUnion(lista_outras)
                    if sentinela:
                        diferença = intersecao.difference(outras)
                        if not diferença.isEmpty():
                            classes[comb] = {'geom': diferença}
                else:
                    intersecao = geoms[comb[0] - 1]
                    sentinela = True
                    for ind in comb[1:]:
                        geom = geoms[ind - 1]
                        if geom.intersects(intersecao):
                            intersecao = intersecao.intersection(geom)
                        else:
                            sentinela = False
                            continue
                    if sentinela:
                        classes[comb] = {'geom': intersecao}
                if feedback.isCanceled():
                    break
                current += 1
                feedback.setProgress(int(current * Percent))
        else:
            # Gerar geometrias por área sem cálculo de sobreposição ("first")
            combs = np.array(valores)[:, np.newaxis]
            classes = {}
            acumulado = geoms[combs[0][0] - 1]
            classes[(1, )] = {'geom': acumulado}
            for k in range(1, len(combs)):
                comb = combs[k]
                geom = geoms[comb[0] - 1]
                diferenca = geom.difference(acumulado)
                classes[(comb[0], )] = {'geom': diferenca}
                acumulado = acumulado.combine(geom)
                if feedback.isCanceled():
                    break

        # Gerar lista com os valores classificados
        Percent = 100.0 / (len(classes))
        current = 0
        for classe in classes:
            feedback.pushInfo(
                (self.tr('Classifying class {}...',
                         'Classificando classe {}...')).format(str(classe)))
            geom = classes[classe]['geom']
            if moldura:
                geom = geom.intersection(moldura_geom)
            if geom.type() == 2:
                if geom.isMultipart():
                    coords = geom.asMultiPolygon()[0][0]
                else:
                    coords = geom.asPolygon()[0]
            else:
                del classes[classe]
                continue
            caminho = []
            for ponto in coords:
                linha = (origem[1] - ponto.y()) / resol_Y
                coluna = (ponto.x() - origem[0]) / resol_X
                caminho += [(linha, coluna)]
            p = path.Path(caminho)
            box = geom.boundingBox()
            uly = box.yMaximum()
            lry = box.yMinimum()
            ulx = box.xMinimum()
            lrx = box.xMaximum()
            # Limites de Varredura
            row_ini = int(round((origem[1] - uly) / resol_Y - 0.5)) - 1
            row_fim = int(round((origem[1] - lry) / resol_Y - 0.5)) + 1
            col_ini = int(round((ulx - origem[0]) / resol_X - 0.5)) - 1
            col_fim = int(round((lrx - origem[0]) / resol_X - 0.5)) + 1
            lin, col = np.meshgrid(np.arange(row_ini, row_fim),
                                   np.arange(col_ini, col_fim))
            LIN = lin.flatten()[:, np.newaxis] + 0.5  # centro do pixel
            COL = col.flatten()[:, np.newaxis] + 0.5
            pixels_center = np.hstack((LIN, COL))
            # Verificando pixels dentro de poligono
            flags = p.contains_points(pixels_center)
            pixels_x = LIN.flatten() * flags
            pixels_y = COL.flatten() * flags
            pixels_x = (pixels_x[pixels_x > 0] - 0.5).astype('int')[:,
                                                                    np.newaxis]
            pixels_y = (pixels_y[pixels_y > 0] - 0.5).astype('int')[:,
                                                                    np.newaxis]
            pixels = np.hstack((pixels_x, pixels_y))
            classes[classe]['pixels'] = pixels
            current += 1
            feedback.setProgress(int(current * Percent))

        # Criar Raster
        Driver = gdal.GetDriverByName('GTiff').Create(Output, n_col, n_lin,
                                                      n_bands, GDT)
        Driver.SetGeoTransform(geotransform)
        Driver.SetProjection(prj)

        # Mosaicar por banda
        Percent = 100.0 / (n_lin * n_col * n_bands)
        current = 0

        for k in range(n_bands):
            feedback.pushInfo(
                (self.tr('Creating band {}...',
                         'Criando banda {}...')).format(str(k + 1)))
            # Criar Array do mosaico
            tipo = gdal_array.GDALTypeCodeToNumericTypeCode(GDT)
            inteiro = True if GDT in (gdal.GDT_Byte, gdal.GDT_UInt16,
                                      gdal.GDT_Int16, gdal.GDT_UInt32,
                                      gdal.GDT_Int32) else False
            banda = np.ones(
                (n_lin, n_col),
                dtype=tipo) * (int(valor_nulo) if inteiro else valor_nulo)
            imgs = {}
            # Para cada classe abrir banda da(s) imagem(ns)
            for classe in classes:
                # Deixando somente imagens a serem utilizadas
                for item in valores:
                    if (item not in classe) and (item in imgs):
                        del imgs[item]
                # Preenchendo dados da imagem no dicionário
                for img in classe:
                    if img not in imgs or len(lista) == 1:
                        img_path = lista[img - 1]
                        image = gdal.Open(img_path)
                        ulx, xres, xskew, uly, yskew, yres = image.GetGeoTransform(
                        )
                        img_origem = (ulx, uly)
                        img_resol_X = abs(xres)
                        img_resol_Y = abs(yres)
                        img_band = image.GetRasterBand(k + 1).ReadAsArray()
                        imgs[img] = {
                            'band': img_band,
                            'xres': img_resol_X,
                            'yres': img_resol_Y,
                            'origem': img_origem
                        }
                        image = None

                if sobrep == 0:  # Se for "primeiro", interpolar apenas da primeira img da comb, caso contrário
                    img = classe[0]
                    # Para cada pixel da classe
                    for px in classes[classe]['pixels']:
                        lin, col = px
                        X = origem[0] + resol_X * (col + 0.5)
                        Y = origem[1] - resol_Y * (lin + 0.5)
                        Interpolado = self.Interpolar(X, Y, imgs[img]['band'],
                                                      imgs[img]['origem'],
                                                      imgs[img]['xres'],
                                                      imgs[img]['yres'],
                                                      reamostragem, valor_nulo)
                        if Interpolado != valor_nulo:
                            banda[lin][col] = round(
                                Interpolado) if inteiro else Interpolado

                        if feedback.isCanceled():
                            break
                        current += 1
                        feedback.setProgress(int(current * Percent))

                else:  # Para cada pixel da classe interpolar o valor da banda de cada img
                    for px in classes[classe]['pixels']:
                        lin, col = px
                        X = origem[0] + resol_X * (col + 0.5)
                        Y = origem[1] - resol_Y * (lin + 0.5)
                        interp_values = []
                        for img in imgs:
                            Interpolado = self.Interpolar(
                                X, Y, imgs[img]['band'], imgs[img]['origem'],
                                imgs[img]['xres'], imgs[img]['yres'],
                                reamostragem, valor_nulo)
                            if Interpolado != valor_nulo:
                                interp_values += [Interpolado]
                        # Calcular o valor agregado (0:first, 1:average, 2:median, 3:min, 4:max) e inserir na banda (se byte, arredondar)
                        if interp_values:
                            if sobrep == 1:
                                result = np.mean(interp_values)
                            elif sobrep == 2:
                                result = np.median(interp_values)
                            elif sobrep == 3:
                                result = np.min(interp_values)
                            elif sobrep == 4:
                                result = np.max(interp_values)
                            banda[lin][col] = round(
                                result) if inteiro else result

                        if feedback.isCanceled():
                            break
                        current += 1
                        feedback.setProgress(int(current * Percent))

            # Salvar banda
            outband = Driver.GetRasterBand(k + 1)
            feedback.pushInfo(
                self.tr('Writing Band {}...'.format(k + 1),
                        'Escrevendo Banda {}...'.format(k + 1)))
            outband.WriteArray(banda)
            if NULO != -1:
                outband.SetNoDataValue(valor_nulo)

        # Salvar e Fechar Raster
        Driver.FlushCache()  # Escrever no disco
        Driver = None  # Salvar e fechar

        feedback.pushInfo(
            self.tr('Operation completed successfully!',
                    'Operação finalizada com sucesso!'))
        feedback.pushInfo('Leandro França - Eng Cart')
        self.CAMINHO = Output
        self.CARREGAR = Carregar
        return {self.MOSAIC: Output}
Example #33
0
    def _hexagonGrid(self, sink, width, height, originX, originY, hSpacing,
                     vSpacing, hOverlay, vOverlay, feedback):
        ft = 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(width) / hOverlay))
        rows = int(math.ceil(float(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 = originX + (col * hOverlay)  # far left
            x2 = x1 + (xVertexHi - xVertexLo)  # left
            x3 = originX + (col * hOverlay) + hSpacing  # right
            x4 = x3 + (xVertexHi - xVertexLo)  # far right

            for row in range(rows):
                if (col % 2) == 0:
                    y1 = originY + (row * vOverlay) - (
                        ((row * 2) + 0) * halfVSpacing)  # hi
                    y2 = originY + (row * vOverlay) - (
                        ((row * 2) + 1) * halfVSpacing)  # mid
                    y3 = originY + (row * vOverlay) - (
                        ((row * 2) + 2) * halfVSpacing)  # lo
                else:
                    y1 = originY + (row * vOverlay) - (
                        ((row * 2) + 1) * halfVSpacing)  # hi
                    y2 = originY + (row * vOverlay) - (
                        ((row * 2) + 2) * halfVSpacing)  # mid
                    y3 = originY + (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))

                ft.setGeometry(QgsGeometry.fromPolygonXY([polyline]))
                ft.setAttributes([x1, y1, x4, y3, id])
                sink.addFeature(ft, QgsFeatureSink.FastInsert)
                id += 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    feedback.setProgress(int(count / cells * 100))
Example #34
0
    def testAreaMeasureAndUnits(self):
        """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the
           calculated areas and units are always consistent
        """

        da = QgsDistanceArea()
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")

        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0),
            ]]
        )

        # We check both the measured area AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
                (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))

        da.setEllipsoid("WGS84")
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        # should always be in Meters Squared
        self.assertAlmostEqual(area, 37416879192.9, delta=0.1)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles)
        self.assertAlmostEqual(area, 14446.7378, delta=0.001)

        # now try with a source CRS which is in feet
        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000)
            ]]
        )
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")
        # measurement should be in square feet
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 2000000, delta=0.001)
        self.assertEqual(units, QgsUnitTypes.AreaSquareFeet)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 222222.2222, delta=0.001)

        da.setEllipsoid("WGS84")
        # now should be in Square Meters again
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 184149.37, delta=1.0)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 220240.8172549, delta=1.0)
Example #35
0
    def draw_circle(self, circle):
        # destination = self.layer.crs()
        destination = self.get_destination_crs()
        source = self.get_project_crs()
        xform_to_latlon = self.crs_transform(source,
                                             destination)  # project to latlon
        xform = self.crs_transform(source,
                                   self.layer.crs())  # project to layer

        polygon = [
            self.transform_point(xform, QgsPointXY(*point))
            for point in circle.to_polygon()
        ]
        print(circle)
        print(polygon)
        print(type(polygon))

        #gPnt = QgsGeometry.fromPointXY(QgsPointXY(1,1))
        #gLine = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)])
        #gPolygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 1), QgsPointXY(2, 2), QgsPointXY(2, 1)]])

        #geometry = QgsGeometry.fromPolygon([polygon])
        geometry = QgsGeometry.fromPolygonXY([polygon])

        feature = QgsFeature()
        feature.setGeometry(geometry)
        feature.setFields(self.layer.fields())

        #print circle.center.x, circle.center.y
        #print(circle.center.x, circle.center.y)

        line = [
            QgsPointXY(circle.center.x, circle.center.y),
            QgsPointXY(circle.center.x, circle.center.y + circle.radius),
        ]

        transformed = [
            self.transform_point(xform, line[0]),
            self.transform_point(xform, line[1]),
        ]

        print("****", transformed)

        #new_line_geometry = QgsGeometry.fromPolyline( [ QgsGeometry.fromPointXY(transformed[0]), QgsGeometry.fromPointXY(transformed[1]) ]  )
        new_line_geometry = QgsGeometry.fromPolyline([
            QgsPoint(transformed[0][0], transformed[0][1]),
            QgsPoint(transformed[1][0], transformed[1][1])
        ])

        distance_area = self.get_distance_area(self.layer)
        actual_line_distance = distance_area.convertLengthMeasurement(
            distance_area.measureLength(new_line_geometry),
            QgsUnitTypes.DistanceMeters)
        # TODO: still cannot convert to meters when layer is geo crs. If a ellips is set to distance_area, the diameter is multiplied a radii when layer is projected crs

        # Translate circle center to units of degrees
        center_in_degrees = xform_to_latlon.transform(circle.center.x,
                                                      circle.center.y)

        # circle_feature.id() is NULL for .shp file
        # and assigned automaticly for .gpkg
        # order is id, diameter, lon, lat
        feature.setAttribute('diameter', actual_line_distance * 2)
        feature.setAttribute('center_lon', center_in_degrees[0])
        feature.setAttribute('center_lat', center_in_degrees[1])

        self.layer.startEditing()
        self.layer.dataProvider().addFeatures([feature])
        #self.layer.addFeature(feature, True)
        self.layer.commitChanges()

        # update layer's extent when new features have been added
        # because change of extent in provider is not propagated to the layer
        self.layer.updateExtents()
 def drawEllipse(self):
     # self.showInfo('Result: ' + str(self.result))
     meanx = self.result[0]
     meany = self.result[1]
     angle1 = self.result[2]
     angle2 = self.result[3]
     SD1 = self.result[4]
     SD2 = self.result[5]
     if self.method == 2:  # CrimeStat
         SD1 = SD1 * (sqrt(2) *
                      sqrt(self.featureCount) /
                      sqrt(self.featureCount - 2))
         SD2 = SD2 * (sqrt(2) *
                      sqrt(self.featureCount) /
                      sqrt(self.featureCount - 2))
     if self.crimestatCorr and self.method != 2:
         SD1 = SD1 * sqrt(2)
         SD2 = SD2 * sqrt(2)
     if self.degfreedCorr and self.method != 2:
         SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 2)
         SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 2)
         # SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 1)
         # SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 1)
     # Find the major and minor axis
     majoraxisangle = angle1
     minoraxisangle = angle2
     majorSD = SD2
     minorSD = SD1
     if SD2 < SD1:
         majoraxisangle = angle2
         minoraxisangle = angle1
         majorSD = SD1
         minorSD = SD2
     # Calculate the "compass" direction angle (clockwise from north)
     direction = 90.0 - majoraxisangle * 180 / pi
     # Calculte the eccentricity
     eccentricity = sqrt(1 - pow(minorSD, 2) / pow(majorSD, 2))
     # Create the memory layer for the ellipse
     sdefields = []
     sdefields.append(QgsField("meanx", QVariant.Double))
     sdefields.append(QgsField("meany", QVariant.Double))
     sdefields.append(QgsField("majoranglerad", QVariant.Double))
     # sdefields.append(QgsField("minoranglerad", QVariant.Double))
     sdefields.append(QgsField("directiondeg", QVariant.Double))
     sdefields.append(QgsField("majorsd", QVariant.Double))
     sdefields.append(QgsField("minorsd", QVariant.Double))
     sdefields.append(QgsField("eccentricity", QVariant.Double))
     layeruri = 'Polygon?'
     layeruri = (layeruri + 'crs=' +
                 str(self.SDLayer.dataProvider().crs().authid()))
     memSDlayer = QgsVectorLayer(layeruri, self.OutputLayerName.text(),
                                 "memory")
     # Set the CRS to the original CRS object
     memSDlayer.setCrs(self.SDLayer.dataProvider().crs())
     memSDlayer.startEditing()  # ?
     for field in sdefields:
         memSDlayer.dataProvider().addAttributes([field])
     sdfeature = QgsFeature()
     theta1 = majoraxisangle
     points = []
     step = pi / 180    # 360 points to draw the ellipse
     t = 0.0
     while t < 2 * pi:
         p1 = QPointF(meanx + majorSD * cos(t) * cos(majoraxisangle) -
                      minorSD * sin(t) * sin(majoraxisangle),
                      meany + majorSD * cos(t) * sin(majoraxisangle) +
                      minorSD * sin(t) * cos(majoraxisangle))
         points.append(QgsPointXY(p1))
         t = t + step
     # Close the polygon
     p1 = QPointF(meanx + majorSD * cos(majoraxisangle),
                  meany + majorSD * sin(majoraxisangle))
     points.append(QgsPointXY(p1))
     sdfeature.setGeometry(QgsGeometry.fromPolygonXY([points]))
     attrs = [meanx, meany, majoraxisangle, direction,
              majorSD, minorSD, eccentricity]
     sdfeature.setAttributes(attrs)
     memSDlayer.dataProvider().addFeatures([sdfeature])
     memSDlayer.commitChanges()  # ?
     memSDlayer.updateExtents()
     QgsProject.instance().addMapLayers([memSDlayer])
Example #37
0
def processPoly(layer, writerLines, isProcessing):
    layercrs = layer.crs()
    if layercrs != epsg4326:
        transto4326 = QgsCoordinateTransform(layercrs, epsg4326, QgsProject.instance())
        transfrom4326 = QgsCoordinateTransform(epsg4326, layercrs, QgsProject.instance())
    
    iterator = layer.getFeatures()
    num_features = 0
    num_bad = 0
    maxseglen = settings.maxSegLength*1000.0
    maxSegments = settings.maxSegments
    for feature in iterator:
        num_features += 1
        try:
            wkbtype = feature.geometry().wkbType()
            if wkbtype == QgsWkbTypes.Polygon:
                poly = feature.geometry().asPolygon()
                numpolygons = len(poly)
                if numpolygons < 1:
                    continue
                
                ptset = []
                for points in poly:
                    numpoints = len(points)
                    if numpoints < 2:
                        continue
                    # If the input is not 4326 we need to convert it to that and then back to the output CRS
                    ptStart = QgsPointXY(points[0][0], points[0][1])
                    if layercrs != epsg4326: # Convert to 4326
                        ptStart = transto4326.transform(ptStart)
                    pts = [ptStart]
                    for x in range(1,numpoints):
                        ptEnd = QgsPointXY(points[x][0], points[x][1])
                        if layercrs != epsg4326: # Convert to 4326
                            ptEnd = transto4326.transform(ptEnd)
                        l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x())
                        n = int(math.ceil(l.s13 / maxseglen))
                        if n > maxSegments:
                            n = maxSegments
                            
                        seglen = l.s13 / n
                        for i in range(1,n):
                            s = seglen * i
                            g = l.Position(s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL)
                            pts.append( QgsPointXY(g['lon2'], g['lat2']) )
                        pts.append(ptEnd)
                        ptStart = ptEnd
     
                    if layercrs != epsg4326: # Convert each point to the output CRS
                        for x, pt in enumerate(pts):
                            pts[x] = transfrom4326.transform(pt)
                    ptset.append(pts)
                        
                if len(ptset) > 0:
                    featureout = QgsFeature()
                    featureout.setGeometry(QgsGeometry.fromPolygonXY(ptset))
                                
                    featureout.setAttributes(feature.attributes())
                    if isProcessing:
                        writerLines.addFeature(featureout)
                    else:
                        writerLines.addFeatures([featureout])
            else:
                multipoly = feature.geometry().asMultiPolygon()
                multiset = []
                for poly in multipoly:
                    ptset = []
                    for points in poly:
                        numpoints = len(points)
                        if numpoints < 2:
                            continue
                        # If the input is not 4326 we need to convert it to that and then back to the output CRS
                        ptStart = QgsPointXY(points[0][0], points[0][1])
                        if layercrs != epsg4326: # Convert to 4326
                            ptStart = transto4326.transform(ptStart)
                        pts = [ptStart]
                        for x in range(1,numpoints):
                            ptEnd = QgsPointXY(points[x][0], points[x][1])
                            if layercrs != epsg4326: # Convert to 4326
                                ptEnd = transto4326.transform(ptEnd)
                            l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x())
                            n = int(math.ceil(l.s13 / maxseglen))
                            if n > maxSegments:
                                n = maxSegments
                                
                            seglen = l.s13 / n
                            for i in range(1,n):
                                s = seglen * i
                                g = l.Position(s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL)
                                pts.append( QgsPointXY(g['lon2'], g['lat2']) )
                            pts.append(ptEnd)
                            ptStart = ptEnd
         
                        if layercrs != epsg4326: # Convert each point to the output CRS
                            for x, pt in enumerate(pts):
                                pts[x] = transfrom4326.transform(pt)
                        ptset.append(pts)
                    multiset.append(ptset)
                        
                if len(multiset) > 0:
                    featureout = QgsFeature()
                    featureout.setGeometry(QgsGeometry.fromMultiPolygonXY(multiset))
                                
                    featureout.setAttributes(feature.attributes())
                    if isProcessing:
                        writerLines.addFeature(featureout)
                    else:
                        writerLines.addFeatures([featureout])
        except:
            num_bad += 1
            #traceback.print_exc()
            pass
                
    return num_bad
    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)

        measureFactor = conversionToMeters(units)

        radius *= measureFactor

        ptSpacing = 360.0 / segments
        srcCRS = source.sourceCrs()
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                                                   self.PrmOutputLayer,
                                                   context, source.fields(),
                                                   QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, source.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()
                # 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)

                # 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))
                f.setAttributes(feature.attributes())
                sink.addFeature(f)
            except:
                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}
Example #39
0
    def canvasPressEvent(self, e):
        if e.button() == Qt.RightButton and len(self.mousePoints) > 0:
            poligon = QgsVectorLayer('Polygon', 'poly', "memory")
            pr = poligon.dataProvider()
            poly = QgsFeature()
            if len(self.mousePoints) > 3:
                self.mousePoints.remove(self.mousePoints[-1])
            poly.setGeometry(QgsGeometry.fromPolygonXY([self.mousePoints]))
            pr.addFeatures([poly])

            layers = self.canvas.layers()
            try:
                for layer in layers:
                    if layer.type() == QgsMapLayer.RasterLayer:
                        continue
                    modifiers = QApplication.keyboardModifiers()
                    if modifiers == Qt.ShiftModifier:
                        processing.run(
                            'qgis:selectbylocation', {
                                'INPUT': layer,
                                'PREDICATE': [0],
                                'INTERSECT': poligon,
                                'METHOD': 3
                            })  # Remove
                    elif modifiers == Qt.ControlModifier:
                        processing.run(
                            'qgis:selectbylocation', {
                                'INPUT': layer,
                                'PREDICATE': [0],
                                'INTERSECT': poligon,
                                'METHOD': 1
                            })  # Add
                    else:
                        processing.run(
                            'qgis:selectbylocation', {
                                'INPUT': layer,
                                'PREDICATE': [0],
                                'INTERSECT': poligon,
                                'METHOD': 0
                            })  # Set
            except Exception:
                self.iface.messageBar().pushMessage(
                    "Warning",
                    "Polygon not valid for selecting elements",
                    level=1,
                    duration=5)
            self.reset()
            poligon = None
            return
        elif e.button() == Qt.RightButton:
            self.canvas.unsetMapTool(self)
            self.deactivate()
            return
        # Rectangle
        if len(self.mousePoints) == 0:
            self.initialPoint = self.toMapCoordinates(e.pos())
            self.finalPoint = self.initialPoint
            self.isSelecting = True
            self.showRectangle(self.initialPoint, self.finalPoint)
        # Poliline
        point = self.toMapCoordinates(e.pos())
        self.mousePoints.append(point)
        if len(self.mousePoints) == 1:
            self.mousePoints.append(point)
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer, context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        anglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context)
        radiuscol = self.parameterAsString(parameters, self.PrmRadiusField, context)
        radius = self.parameterAsDouble(parameters, self.PrmRadius, context)
        startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context)
        segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context)
        export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context)
        
        # The algorithm creates the heart on its side so this rotates
        # it so that it is upright.
        startAngle -= 90.0
        
        measureFactor = conversionToMeters(units)
        radius *= measureFactor

        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
        
        step = 360.0 / segments
        numbad = 0
        iterator = source.getFeatures()
        for index, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                if anglecol:
                    sangle = float(feature[anglecol]) - 90
                else:
                    sangle = startAngle
                if radiuscol:
                    radius2 = float(feature[radiuscol]) * measureFactor
                else:
                    radius2 = radius
            except:
                numbad += 1
                continue
            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())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle)
                sina = math.sin(a)
                x = 16 * sina * sina * sina
                y = 13 * math.cos(a) - 5 * math.cos(2*a) - 2 * math.cos(3 * a)- math.cos(4*a)
                dist = math.sqrt(x*x + y*y) * radius2 / 17.0
                a2 = math.degrees(math.atan2(y,x))+sangle
                g = geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += step
                
            # 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)
            
            if index % 100 == 0:
                feedback.setProgress(int(index * total))
            
        if numbad > 0:
            feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount)))
        
        return {self.PrmOutputLayer: dest_id}
    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]
                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 = [(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(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 = [(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))
Example #42
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        sidescol = self.parameterAsString(parameters,
                                          self.PrmNumberOfSidesField, context)
        anglecol = self.parameterAsString(parameters,
                                          self.PrmStartingAngleField, context)
        distcol = self.parameterAsString(parameters, self.PrmRadiusField,
                                         context)
        sides = self.parameterAsInt(parameters, self.PrmDefaultNumberOfSides,
                                    context)
        angle = self.parameterAsDouble(parameters,
                                       self.PrmDefaultStartingAngle, context)
        defaultDist = self.parameterAsInt(parameters, self.PrmDefaultRadius,
                                          context)
        unitOfDist = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                         context)

        measureFactor = conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        srcCRS = source.sourceCrs()
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                                                   self.PrmOutputLayer,
                                                   context, source.fields(),
                                                   QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, source.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

        iterator = source.getFeatures()
        numbad = 0
        for cnt, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                pt = feature.geometry().asPoint()
                if srcCRS != epsg4326:
                    pt = geomTo4326.transform(pt.x(), pt.y())
                if sidescol:
                    s = int(feature[sidescol])
                else:
                    s = sides
                if anglecol:
                    startangle = float(feature[anglecol])
                else:
                    startangle = angle
                if distcol:
                    d = float(feature[distcol]) * measureFactor
                else:
                    d = defaultDist
                pts = []
                i = s
                while i >= 0:
                    a = (i * 360.0 / s) + startangle
                    i -= 1
                    g = geod.Direct(pt.y(), pt.x(), a, d,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))

                # 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))
                f.setAttributes(feature.attributes())
                sink.addFeature(f)
            except:
                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}
Example #43
0
    def addEntitySetToPolygon(self, entitySet, removeOriginals=False):
        """
      Aggiunge il set di entità al poligono da modificare
      """
        geom = self.poligonEntity.getGeometry()
        layerList = []
        layerList.append(self.poligonEntity.layer)

        for layerEntitySet in entitySet.layerEntitySetList:
            layer = layerEntitySet.layer
            if layer.geometryType(
            ) != QgsWkbTypes.PolygonGeometry and layer.geometryType(
            ) != QgsWkbTypes.LineGeometry:
                self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                return False

            if removeOriginals: layerList.append(layer)
            coordTransform = QgsCoordinateTransform(
                layer.crs(), self.poligonEntity.layer.crs(),
                QgsProject.instance())

            for featureId in layerEntitySet.featureIds:
                # se la feature è quella di polygonEntity è errore
                if layer.id() == self.poligonEntity.layerId(
                ) and featureId == self.poligonEntity.featureId:
                    self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                    return False

                f = layerEntitySet.getFeature(featureId)
                # trasformo la geometria nel crs del layer del poligono da modificare
                geomToAdd = f.geometry()
                geomToAdd.transform(coordTransform)

                # se il poligono è contenuto nella geometria da aggiungere
                if geomToAdd.contains(geom):
                    # Riduco la geometria in point o polyline
                    simplifiedGeoms = qad_utils.asPointOrPolyline(geom)
                    # deve essere un poligono senza ring
                    if len(simplifiedGeoms) != 1 or simplifiedGeoms[0].wkbType(
                    ) != QgsWkbTypes.LineString:
                        self.showMsg(QadMsg.translate("QAD",
                                                      "Invalid object."))
                        return False
                    points = simplifiedGeoms[0].asPolyline(
                    )  # vettore di punti
                    # aggiungo un'isola
                    if geomToAdd.addRing(points) != 0:  # 0 in case of success
                        self.showMsg(QadMsg.translate("QAD",
                                                      "Invalid object."))
                        return False
                    del geom
                    geom = QgsGeometry.fromPolygonXY(geomToAdd.asPolygon())
                else:  # se il poligono non è contenuto nella geometria da aggiungere
                    # Riduco la geometria in point o polyline
                    simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
                    for simplifiedGeom in simplifiedGeoms:
                        # se la geometria da aggiungere è contenuta nel poligono
                        if geom.contains(simplifiedGeom):
                            points = simplifiedGeom.asPolyline(
                            )  # vettore di punti
                            # aggiungo un'isola
                            if geom.addRing(
                                    points) != 0:  # 0 in case of success
                                self.showMsg(
                                    QadMsg.translate("QAD", "Invalid object."))
                                return False
                        else:
                            # aggiungo una parte
                            if geom.addPartGeometry(
                                    simplifiedGeom) != QgsGeometry.Success:
                                self.showMsg(
                                    QadMsg.translate("QAD", "Invalid object."))
                                return False

        f = self.poligonEntity.getFeature()
        f.setGeometry(geom)

        layerList = entitySet.getLayerList()
        layerList.append(self.poligonEntity.layer)

        self.plugIn.beginEditCommand("Feature edited", layerList)

        # plugIn, layer, feature, refresh, check_validity
        if qad_layer.updateFeatureToLayer(self.plugIn,
                                          self.poligonEntity.layer, f, False,
                                          False) == False:
            self.plugIn.destroyEditCommand()
            return False

        if removeOriginals:
            for layerEntitySet in entitySet.layerEntitySetList:
                if qad_layer.deleteFeaturesToLayer(self.plugIn,
                                                   layerEntitySet.layer,
                                                   layerEntitySet.featureIds,
                                                   False) == False:
                    self.plugIn.destroyEditCommand()
                    return

        self.plugIn.endEditCommand()
        self.nOperationsToUndo = self.nOperationsToUndo + 1

        return True
def processPoly(source, sink, feedback, maxseglen):
    layercrs = source.sourceCrs()
    if layercrs != epsg4326:
        transto4326 = QgsCoordinateTransform(layercrs, epsg4326,
                                             QgsProject.instance())
        transfrom4326 = QgsCoordinateTransform(epsg4326, layercrs,
                                               QgsProject.instance())

    total = 100.0 / source.featureCount() if source.featureCount() else 0
    iterator = source.getFeatures()
    num_bad = 0
    for cnt, feature in enumerate(iterator):
        if feedback.isCanceled():
            break
        try:
            if not feature.geometry().isMultipart():
                poly = feature.geometry().asPolygon()
                numpolygons = len(poly)
                if numpolygons < 1:
                    continue

                ptset = []
                # Iterate through all points in the polygon and if the distance
                # is greater than the maxseglen, then add additional points.
                for points in poly:
                    numpoints = len(points)
                    if numpoints < 2:
                        continue
                    # If the input is not 4326 we need to convert it to that and then back to the output CRS
                    ptStart = QgsPointXY(points[0][0], points[0][1])
                    if layercrs != epsg4326:  # Convert to 4326
                        ptStart = transto4326.transform(ptStart)
                    pts = [ptStart]
                    for x in range(1, numpoints):
                        ptEnd = QgsPointXY(points[x][0], points[x][1])
                        if layercrs != epsg4326:  # Convert to 4326
                            ptEnd = transto4326.transform(ptEnd)
                        l = geod.InverseLine(ptStart.y(), ptStart.x(),
                                             ptEnd.y(), ptEnd.x())
                        # Check to see if the distance is greater than the maximum
                        # segment length and if so lets add additional points.
                        if l.s13 > maxseglen:
                            n = int(math.ceil(l.s13 / maxseglen))
                            seglen = l.s13 / n
                            for i in range(1, n):
                                s = seglen * i
                                g = l.Position(
                                    s, Geodesic.LATITUDE | Geodesic.LONGITUDE
                                    | Geodesic.LONG_UNROLL)
                                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                        pts.append(ptEnd)
                        ptStart = ptEnd

                    if layercrs != epsg4326:  # Convert each point to the output CRS
                        for x, pt in enumerate(pts):
                            pts[x] = transfrom4326.transform(pt)
                    ptset.append(pts)

                if len(ptset) > 0:
                    featureout = QgsFeature()
                    featureout.setGeometry(QgsGeometry.fromPolygonXY(ptset))

                    featureout.setAttributes(feature.attributes())
                    sink.addFeature(featureout)
            else:
                multipoly = feature.geometry().asMultiPolygon()
                multiset = []
                for poly in multipoly:
                    ptset = []
                    for points in poly:
                        numpoints = len(points)
                        if numpoints < 2:
                            continue
                        # If the input is not 4326 we need to convert it to that and then back to the output CRS
                        ptStart = QgsPointXY(points[0][0], points[0][1])
                        if layercrs != epsg4326:  # Convert to 4326
                            ptStart = transto4326.transform(ptStart)
                        pts = [ptStart]
                        for x in range(1, numpoints):
                            ptEnd = QgsPointXY(points[x][0], points[x][1])
                            if layercrs != epsg4326:  # Convert to 4326
                                ptEnd = transto4326.transform(ptEnd)
                            l = geod.InverseLine(ptStart.y(), ptStart.x(),
                                                 ptEnd.y(), ptEnd.x())
                            if l.s13 > maxseglen:
                                n = int(math.ceil(l.s13 / maxseglen))
                                seglen = l.s13 / n
                                for i in range(1, n):
                                    s = seglen * i
                                    g = l.Position(
                                        s,
                                        Geodesic.LATITUDE | Geodesic.LONGITUDE
                                        | Geodesic.LONG_UNROLL)
                                    pts.append(QgsPointXY(
                                        g['lon2'], g['lat2']))
                            pts.append(ptEnd)
                            ptStart = ptEnd

                        if layercrs != epsg4326:  # Convert each point to the output CRS
                            for x, pt in enumerate(pts):
                                pts[x] = transfrom4326.transform(pt)
                        ptset.append(pts)
                    multiset.append(ptset)

                if len(multiset) > 0:
                    featureout = QgsFeature()
                    featureout.setGeometry(
                        QgsGeometry.fromMultiPolygonXY(multiset))

                    featureout.setAttributes(feature.attributes())
                    sink.addFeature(featureout)
        except:
            num_bad += 1
            '''s = traceback.format_exc()
            feedback.pushInfo(s)'''

        feedback.setProgress(int(cnt * total))
    return num_bad
Example #45
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))
Example #46
0
    def unionIntersSubtractEntitySetToPolygon(self,
                                              entitySet,
                                              opType,
                                              removeOriginals=False):
        """
      Unisce o interseca i poligoni di entitySet al poligono corrente
      """
        geom = self.poligonEntity.getGeometry()
        layerList = []
        layerList.append(self.poligonEntity.layer)

        geomList = []
        geomList.append(geom)
        for layerEntitySet in entitySet.layerEntitySetList:
            del geomList[:]
            layer = layerEntitySet.layer
            coordTransform = QgsCoordinateTransform(
                layer.crs(), self.poligonEntity.layer.crs(),
                QgsProject.instance())

            if layer.geometryType() == QgsWkbTypes.PolygonGeometry:
                for featureId in layerEntitySet.featureIds:
                    # se la feature è quella di polygonEntity è errore
                    if layer.id() == self.poligonEntity.layerId(
                    ) and featureId == self.poligonEntity.featureId:
                        self.showMsg(QadMsg.translate("QAD",
                                                      "Invalid object."))
                        return False
                    f = layerEntitySet.getFeature(featureId)
                    # trasformo la geometria nel crs del layer del poligono da modificare
                    geomToAdd = f.geometry()

                    geomToAdd.transform(coordTransform)

                    if opType == QadMAPMPEDITCommandOpTypeEnum.UNION:
                        geom = geom.combine(geomToAdd)
                    elif opType == QadMAPMPEDITCommandOpTypeEnum.INTERSECTION:
                        geom = geom.intersection(geomToAdd)
                    elif opType == QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE:
                        geom = geom.difference(geomToAdd)

                    if geom is None:
                        self.showMsg(QadMsg.translate("QAD",
                                                      "Invalid object."))
                        return False

                    if removeOriginals and layer.id(
                    ) != self.poligonEntity.layerId():
                        layerList.append(layer)

            elif layer.geometryType() == QgsWkbTypes.LineGeometry:
                for featureId in layerEntitySet.featureIds:
                    f = layerEntitySet.getFeature(featureId)
                    # trasformo la geometria nel crs del layer del poligono da modificare
                    geomToAdd = f.geometry()
                    geomToAdd.transform(coordTransform)
                    # Riduco la geometria in point o polyline
                    simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd)
                    for simplifiedGeom in simplifiedGeoms:
                        if simplifiedGeom.wkbType() != QgsWkbTypes.LineString:
                            self.showMsg(
                                QadMsg.translate("QAD", "Invalid object."))
                            return False
                        points = simplifiedGeom.asPolyline(
                        )  # vettore di punti

                        if len(points) < 4 or points[0] != points[
                                -1]:  # polilinea chiusa con almeno 4 punti (primo e ultimo uguali)
                            self.showMsg(
                                QadMsg.translate("QAD", "Invalid object."))
                            return False
                        geomToAdd = QgsGeometry.fromPolygonXY([points])

                        if opType == QadMAPMPEDITCommandOpTypeEnum.UNION:
                            geom = geom.combine(geomToAdd)
                        elif opType == QadMAPMPEDITCommandOpTypeEnum.INTERSECTION:
                            geom = geom.intersection(geomToAdd)
                        elif opType == QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE:
                            geom = geom.difference(geomToAdd)

                        if geom is None or geom.type(
                        ) != QgsWkbTypes.PolygonGeometry:
                            self.showMsg(
                                QadMsg.translate("QAD", "Invalid object."))
                            return False

                    if removeOriginals: layerList.append(layer)
            else:
                self.showMsg(QadMsg.translate("QAD", "Invalid object."))
                return False

        f = self.poligonEntity.getFeature()
        f.setGeometry(geom)

        self.plugIn.beginEditCommand("Feature edited", layerList)

        # plugIn, layer, feature, refresh, check_validity
        if qad_layer.updateFeatureToLayer(self.plugIn,
                                          self.poligonEntity.layer, f, False,
                                          False) == False:
            self.plugIn.destroyEditCommand()
            return False

        if removeOriginals:
            for layerEntitySet in entitySet.layerEntitySetList:
                if qad_layer.deleteFeaturesToLayer(self.plugIn,
                                                   layerEntitySet.layer,
                                                   layerEntitySet.featureIds,
                                                   False) == False:
                    self.plugIn.destroyEditCommand()
                    return

        self.plugIn.endEditCommand()
        self.nOperationsToUndo = self.nOperationsToUndo + 1

        return True
    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]
                # 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 == 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 = []
                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(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 = []
                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))
Example #48
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)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, source.fields(),
                                               source.wkbType(),
                                               source.sourceCrs())

        # 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()
        print(features)

        for current, feature in enumerate(features):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break
            # sshuair begin
            geom = feature.geometry()
            attrs = feature.attributes()
            geom_type = geom.wkbType()

            feature_new = QgsFeature()

            # Point
            if geom_type == 1:
                vertices = geom.asPoint()
                vert_new = bd2wgs(vertices[0], vertices[1])
                feature_new.setGeometry(
                    QgsGeometry.fromPointXY(
                        QgsPointXY(vert_new[0], vert_new[1])))

            # LineString
            elif geom_type == 2:
                vert_new = []
                vertices = geom.asPolyline()
                for pt in vertices:
                    pt_new = bd2wgs(pt[0], pt[1])
                    vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
                feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))

            # Polygon
            elif geom_type == 3:
                vertices = geom.asPolygon()
                vert_new = []
                for ring in vertices:
                    ring_vert = []
                    for pt in ring:
                        pt_new = bd2wgs(pt[0], pt[1])
                        ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
                    vert_new.append(ring_vert)
                feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))

            # MultiPoint
            elif geom_type == 4:
                vert_new = []
                vertices = geom.asMultiPoint()
                for pt in vertices:
                    pt_new = bd2wgs(pt[0], pt[1])
                    vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
                feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))

            # MultiLineString
            elif geom_type == 5:
                vertices = geom.asMultiPolyline()
                vert_new = []
                for part in vertices:
                    linestring = []
                    for pt in part:
                        pt_new = bd2wgs(pt[0], pt[1])
                        linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
                    vert_new.append(linestring)
                feature_new.setGeometry(
                    QgsGeometry.fromMultiPolylineXY(vert_new))

            # MultiPolygon
            elif geom_type == 6:
                vertices = geom.asMultiPolygon()
                vert_new = []
                for part in vertices:
                    poly = []
                    for ring in part:
                        ring_vert = []
                        for pt in ring:
                            pt_new = bd2wgs(pt[0], pt[1])
                            ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
                        poly.append(ring_vert)
                    vert_new.append(poly)
                feature_new.setGeometry(
                    QgsGeometry.fromMultiPolygonXY(vert_new))
            else:
                continue

            feature_new.setAttributes(attrs)
            # sshuair end

            # feature = feature+0.1
            # Add a feature in the sink
            sink.addFeature(feature_new, QgsFeatureSink.FastInsert)

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

        # 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}