Exemple #1
0
 def convertToPolygon(self, geom):
     if QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PointGeometry and geom.constGet().nCoordinates() < 3:
         raise QgsProcessingException(
             self.tr('Cannot convert from Point to Polygon').format(QgsWkbTypes.displayString(geom.wkbType())))
     elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PointGeometry:
         # multipoint with at least 3 points
         # TODO: mega inefficient - needs rework when geometry iterators land
         # (but at least it doesn't lose Z/M values)
         points = []
         for g in geom.constGet().coordinateSequence():
             for r in g:
                 for p in r:
                     points.append(p)
         linestring = QgsLineString(points)
         linestring.close()
         p = QgsPolygon()
         p.setExteriorRing(linestring)
         return [QgsGeometry(p)]
     elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.LineGeometry:
         if QgsWkbTypes.isMultiType(geom):
             parts = []
             for i in range(geom.constGet().numGeometries()):
                 p = QgsPolygon()
                 linestring = geom.constGet().geometryN(i).clone()
                 linestring.close()
                 p.setExteriorRing(linestring)
                 parts.append(QgsGeometry(p))
             return QgsGeometry.collectGeometry(parts)
         else:
             # linestring to polygon
             p = QgsPolygon()
             linestring = geom.constGet().clone()
             linestring.close()
             p.setExteriorRing(linestring)
             return [QgsGeometry(p)]
     else:
         #polygon
         if QgsWkbTypes.isMultiType(geom):
             return geom.asGeometryCollection()
         else:
             return [geom]
Exemple #2
0
    def testJSONExporter(self):
        """ test converting features to GeoJSON """
        fields = QgsFields()
        fields.append(QgsField("name", QVariant.String))
        fields.append(QgsField("cost", QVariant.Double))
        fields.append(QgsField("population", QVariant.Int))

        feature = QgsFeature(fields, 5)
        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
        feature.setAttributes(['Valsier Peninsula', 6.8, 198])

        exporter = QgsJsonExporter()

        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test with linestring for bbox inclusion
        l = QgsLineString()
        l.setPoints([QgsPoint(5, 6), QgsPoint(15, 16)])
        feature.setGeometry(QgsGeometry(QgsLineString(l)))

        expected = """{
   "type":"Feature",
   "id":5,
   "bbox":[5, 6, 15, 16],
   "geometry":
   {"type": "LineString", "coordinates": [ [5, 6], [15, 16]]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test that precision is respected
        feature.setGeometry(QgsGeometry(QgsPoint(5.444444444, 6.333333333)))
        exporter.setPrecision(3)
        self.assertEqual(exporter.precision(), 3)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5.444, 6.333]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
        exporter.setPrecision(17)

        # test that attribute subset is respected
        exporter.setAttributes([0, 2])
        self.assertEqual(exporter.attributes(), [0, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setAttributes([1])
        self.assertEqual(exporter.attributes(), [1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "cost":6.8
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setAttributes([])

        # text excluding attributes

        exporter.setExcludedAttributes([1])
        self.assertEqual(exporter.excludedAttributes(), [1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setExcludedAttributes([1, 2])
        self.assertEqual(exporter.excludedAttributes(), [1, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula"
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setExcludedAttributes([0, 1, 2])
        self.assertEqual(exporter.excludedAttributes(), [0, 1, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test that excluded attributes take precedence over included

        exporter.setAttributes([1, 2])
        exporter.setExcludedAttributes([0, 1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setAttributes([])
        exporter.setExcludedAttributes([])

        # test excluding geometry
        exporter.setIncludeGeometry(False)
        self.assertEqual(exporter.includeGeometry(), False)
        feature.setGeometry(QgsGeometry(QgsLineString(l)))

        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setIncludeGeometry(True)

        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))

        # test excluding attributes
        exporter.setIncludeAttributes(False)
        self.assertEqual(exporter.includeAttributes(), False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setIncludeGeometry(False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setIncludeAttributes(True)

        # test overriding ID
        expected = """{
   "type":"Feature",
   "id":29,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature, id=29), expected)

        # test injecting extra attributes
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198,
      "extra":"val1",
      "extra2":2
   }
}"""
        self.assertEqual(
            exporter.exportFeature(feature,
                                   extraProperties={
                                       "extra": "val1",
                                       "extra2": 2
                                   }), expected)

        exporter.setIncludeAttributes(False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "extra":"val1",
      "extra2":{"nested_map":5,
"nested_map2":"val"},
      "extra3":[1,2,3]
   }
}"""
        expected2 = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "extra":"val1",
      "extra2":{"nested_map":5,"nested_map2":"val"},
      "extra3":[1,2,3]
   }
}"""
        exp_f = exporter.exportFeature(feature,
                                       extraProperties={
                                           "extra": "val1",
                                           "extra2": {
                                               "nested_map": 5,
                                               "nested_map2": "val"
                                           },
                                           "extra3": [1, 2, 3]
                                       })
        self.assertTrue(exp_f == expected or exp_f == expected2)
        exporter.setIncludeGeometry(True)
Exemple #3
0
 def testQgsLineStringRepr(self):
     ls = QgsLineString([QgsPoint(10, 2), QgsPoint(10, 1), QgsPoint(5, 1)])
     self.assertEqual(ls.__repr__(),
                      '<QgsLineString: LineString (10 2, 10 1, 5 1)>')
Exemple #4
0
    def txestGeometryRendering(self):
        '''Tests rendering a bunch of different geometries, including bad/odd geometries.'''

        empty_multipolygon = QgsMultiPolygon()
        empty_multipolygon.addGeometry(QgsPolygon())
        empty_polygon = QgsPolygon()
        empty_linestring = QgsLineString()

        tests = [{'name': 'Point',
                  'wkt': 'Point (1 2)',
                  'reference_image': 'point'},
                 {'name': 'MultiPoint',
                  'wkt': 'MultiPoint ((10 30),(40 20),(30 10),(20 10))',
                  'reference_image': 'multipoint'},
                 {'name': 'LineString',
                  'wkt': 'LineString (0 0,3 4,4 3)',
                  'reference_image': 'linestring'},
                 {'name': 'Empty LineString',
                  'geom': QgsGeometry(empty_linestring),
                  'reference_image': 'empty'},
                 {'name': 'MultiLineString',
                  'wkt': 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 1, 5 1, 5 0, 6 0))',
                  'reference_image': 'multilinestring'},
                 {'name': 'Polygon',
                  'wkt': 'Polygon ((0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5))',
                  'reference_image': 'polygon'},
                 {'name': 'Empty Polygon',
                  'geom': QgsGeometry(empty_polygon),
                  'reference_image': 'empty'},
                 {'name': 'MultiPolygon',
                  'wkt': 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))',
                  'reference_image': 'multipolygon'},
                 {'name': 'Empty MultiPolygon',
                  'geom': QgsGeometry(empty_multipolygon),
                  'reference_image': 'empty'},
                 {'name': 'CircularString',
                  'wkt': 'CIRCULARSTRING(268 415,227 505,227 406)',
                  'reference_image': 'circular_string'},
                 {'name': 'CompoundCurve',
                  'wkt': 'COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))',
                  'reference_image': 'compound_curve'},
                 {'name': 'CurvePolygon',
                  'wkt': 'CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))',
                  'reference_image': 'curve_polygon'},
                 {'name': 'MultiCurve',
                  'wkt': 'MultiCurve((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0, 2 1,2 2))',
                  'reference_image': 'multicurve'},
                 {'name': 'CurvePolygon_no_arc',  # refs #14028
                  'wkt': 'CURVEPOLYGON(LINESTRING(1 3, 3 5, 4 7, 7 3, 1 3))',
                  'reference_image': 'curve_polygon_no_arc'}]

        for test in tests:

            def get_geom():
                if 'geom' not in test:
                    geom = QgsGeometry.fromWkt(test['wkt'])
                    assert geom and not geom.isNull(), 'Could not create geometry {}'.format(test['wkt'])
                else:
                    geom = test['geom']
                return geom

            geom = get_geom()
            rendered_image = self.renderGeometry(geom)
            assert self.imageCheck(test['name'], test['reference_image'], rendered_image)

            # Note - each test is repeated with the same geometry and reference image, but with added
            # z and m dimensions. This tests that presence of the dimensions does not affect rendering

            # test with Z
            geom_z = get_geom()
            geom_z.get().addZValue(5)
            rendered_image = self.renderGeometry(geom_z)
            assert self.imageCheck(test['name'] + 'Z', test['reference_image'], rendered_image)

            # test with ZM
            geom_z.get().addMValue(15)
            rendered_image = self.renderGeometry(geom_z)
            assert self.imageCheck(test['name'] + 'ZM', test['reference_image'], rendered_image)

            # test with M
            geom_m = get_geom()
            geom_m.get().addMValue(15)
            rendered_image = self.renderGeometry(geom_m)
            assert self.imageCheck(test['name'] + 'M', test['reference_image'], rendered_image)
Exemple #5
0
    def _lineGrid(self, sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback):
        feat = QgsFeature()

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        count = 0
        id = 1

        # latitude lines
        count_max = bbox.height() / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            if feedback.isCanceled():
                break

            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = QgsLineString([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(),
                                y,
                                bbox.xMaximum(),
                                y,
                                id,
                                y])
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = bbox.width() / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            if feedback.isCanceled():
                break

            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = QgsLineString([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x,
                                bbox.yMaximum(),
                                x,
                                bbox.yMinimum(),
                                id,
                                x])
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))
Exemple #6
0
    def processAlgorithm(self, context, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        hSpacing = self.getParameterValue(self.HSPACING)
        vSpacing = self.getParameterValue(self.VSPACING)
        hOverlay = self.getParameterValue(self.HOVERLAY)
        vOverlay = self.getParameterValue(self.VOVERLAY)
        crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if width < hSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Horizontal spacing is too small for the covered area'))

        if height < vSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Vertical spacing is too small for the covered area'))

        fields = [QgsField('left', QVariant.Double, '', 24, 16),
                  QgsField('top', QVariant.Double, '', 24, 16),
                  QgsField('right', QVariant.Double, '', 24, 16),
                  QgsField('bottom', QVariant.Double, '', 24, 16),
                  QgsField('id', QVariant.Int, '', 10, 0),
                  QgsField('coord', QVariant.Double, '', 24, 15)
                  ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, crs, context)

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPointV2(bbox.xMinimum(), y)
            pt2 = QgsPointV2(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(),
                                y,
                                bbox.xMaximum(),
                                y,
                                id,
                                y])
            writer.addFeature(feat)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPointV2(x, bbox.yMaximum())
            pt2 = QgsPointV2(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x,
                                bbox.yMaximum(),
                                x,
                                bbox.yMinimum(),
                                id,
                                x])
            writer.addFeature(feat)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        del writer
Exemple #7
0
    def testRenderWithTransform(self):
        layer = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())

        item = QgsAnnotationPolygonItem(
            QgsPolygon(
                QgsLineString([
                    QgsPoint(11.5, 13),
                    QgsPoint(12, 13),
                    QgsPoint(12, 13.5),
                    QgsPoint(11.5, 13)
                ])))
        item.setSymbol(
            QgsFillSymbol.createSimple({
                'color': '200,100,100',
                'outline_color': 'black',
                'outline_width': '2'
            }))
        item.setZIndex(1)
        layer.addItem(item)

        item = QgsAnnotationLineItem(
            QgsLineString(
                [QgsPoint(11, 13),
                 QgsPoint(12, 13),
                 QgsPoint(12, 15)]))
        item.setSymbol(
            QgsLineSymbol.createSimple({
                'color': '#ffff00',
                'line_width': '3'
            }))
        item.setZIndex(2)
        layer.addItem(item)

        item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
        item.setSymbol(
            QgsMarkerSymbol.createSimple({
                'color': '100,200,200',
                'size': '6',
                'outline_color': 'black'
            }))
        item.setZIndex(3)
        layer.addItem(item)

        layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

        settings = QgsMapSettings()
        settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
        settings.setExtent(QgsRectangle(1250958, 1386945, 1420709, 1532518))
        settings.setOutputSize(QSize(300, 300))

        settings.setFlag(QgsMapSettings.Antialiasing, False)

        rc = QgsRenderContext.fromMapSettings(settings)
        rc.setCoordinateTransform(
            QgsCoordinateTransform(layer.crs(), settings.destinationCrs(),
                                   QgsProject.instance()))
        image = QImage(200, 200, QImage.Format_ARGB32)
        image.setDotsPerMeterX(96 / 25.4 * 1000)
        image.setDotsPerMeterY(96 / 25.4 * 1000)
        image.fill(QColor(255, 255, 255))
        painter = QPainter(image)
        rc.setPainter(painter)

        try:
            renderer = layer.createMapRenderer(rc)
            renderer.render()
        finally:
            painter.end()

        self.assertTrue(
            self.imageCheck('layer_render_transform', 'layer_render_transform',
                            image))
    def test_render_via_job_with_transform(self):
        """
        Test rendering an annotation layer via a map render job
        """
        layer = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())

        item = QgsAnnotationPolygonItem(
            QgsPolygon(
                QgsLineString([
                    QgsPoint(11.5, 13),
                    QgsPoint(12, 13),
                    QgsPoint(12, 13.5),
                    QgsPoint(11.5, 13)
                ])))
        item.setSymbol(
            QgsFillSymbol.createSimple({
                'color': '200,100,100',
                'outline_color': 'black',
                'outline_width': '2'
            }))
        item.setZIndex(1)
        i1_id = layer.addItem(item)

        item = QgsAnnotationLineItem(
            QgsLineString(
                [QgsPoint(11, 13),
                 QgsPoint(12, 13),
                 QgsPoint(12, 15)]))
        item.setSymbol(
            QgsLineSymbol.createSimple({
                'color': '#ffff00',
                'line_width': '3'
            }))
        item.setZIndex(2)
        i2_id = layer.addItem(item)

        item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
        item.setSymbol(
            QgsMarkerSymbol.createSimple({
                'color': '100,200,200',
                'size': '6',
                'outline_color': 'black'
            }))
        item.setZIndex(3)
        i3_id = layer.addItem(item)

        layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

        settings = QgsMapSettings()
        settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
        settings.setExtent(QgsRectangle(1250958, 1386945, 1420709, 1532518))
        settings.setOutputSize(QSize(200, 200))
        settings.setLayers([layer])

        job = QgsMapRendererSequentialJob(settings)
        job.start()
        job.waitForFinished()

        # check rendered item results
        item_results = job.takeRenderedItemResults()
        item_details = item_results.renderedItems()
        self.assertEqual(len(item_details), 3)
        self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3)
        self.assertCountEqual([i.itemId() for i in item_details],
                              [i1_id, i2_id, i3_id])
        # bounds should be in map crs
        self.assertEqual(
            [
                QgsGeometry.fromRect(i.boundingBox()).asWkt(0)
                for i in item_details if i.itemId() == i1_id
            ][0],
            'Polygon ((1280174 1459732, 1335834 1459732, 1335834 1516914, 1280174 1516914, 1280174 1459732))'
        )
        self.assertEqual(
            [
                QgsGeometry.fromRect(i.boundingBox()).asWkt(0)
                for i in item_details if i.itemId() == i2_id
            ][0],
            'Polygon ((1224514 1459732, 1335834 1459732, 1335834 1689200, 1224514 1689200, 1224514 1459732))'
        )
        expected = 'Polygon ((1325786 1449684, 1345882 1449684, 1345882 1469780, 1325786 1469780, 1325786 1449684))'
        result = [
            QgsGeometry.fromRect(i.boundingBox()).asWkt(0)
            for i in item_details if i.itemId() == i3_id
        ][0]
        self.assertTrue(
            compareWkt(result, expected, tol=1000),
            "mismatch Expected:\n{}\nGot:\n{}\n".format(expected, result))
    def testItems(self):
        layer = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())

        self.assertTrue(layer.isEmpty())

        polygon_item_id = layer.addItem(
            QgsAnnotationPolygonItem(
                QgsPolygon(
                    QgsLineString([
                        QgsPoint(12, 13),
                        QgsPoint(14, 13),
                        QgsPoint(14, 15),
                        QgsPoint(12, 13)
                    ]))))
        linestring_item_id = layer.addItem(
            QgsAnnotationLineItem(
                QgsLineString(
                    [QgsPoint(11, 13),
                     QgsPoint(12, 13),
                     QgsPoint(12, 15)])))
        marker_item_id = layer.addItem(
            QgsAnnotationMarkerItem(QgsPoint(12, 13)))

        self.assertEqual(len(layer.items()), 3)
        self.assertFalse(layer.isEmpty())

        self.assertIsInstance(layer.items()[polygon_item_id],
                              QgsAnnotationPolygonItem)
        self.assertIsInstance(layer.items()[linestring_item_id],
                              QgsAnnotationLineItem)
        self.assertIsInstance(layer.items()[marker_item_id],
                              QgsAnnotationMarkerItem)

        self.assertFalse(layer.removeItem('xxxx'))
        self.assertEqual(len(layer.items()), 3)
        self.assertTrue(layer.removeItem(linestring_item_id))
        self.assertEqual(len(layer.items()), 2)
        self.assertIsInstance(layer.items()[polygon_item_id],
                              QgsAnnotationPolygonItem)
        self.assertIsInstance(layer.items()[marker_item_id],
                              QgsAnnotationMarkerItem)
        self.assertFalse(layer.removeItem(linestring_item_id))

        self.assertTrue(layer.removeItem(polygon_item_id))
        self.assertEqual(len(layer.items()), 1)
        self.assertIsInstance(layer.items()[marker_item_id],
                              QgsAnnotationMarkerItem)

        self.assertTrue(layer.removeItem(marker_item_id))
        self.assertEqual(len(layer.items()), 0)
        self.assertTrue(layer.isEmpty())

        layer.addItem(
            QgsAnnotationPolygonItem(
                QgsPolygon(
                    QgsLineString([
                        QgsPoint(12, 13),
                        QgsPoint(14, 13),
                        QgsPoint(14, 15),
                        QgsPoint(12, 13)
                    ]))))
        layer.addItem(
            QgsAnnotationLineItem(
                QgsLineString(
                    [QgsPoint(11, 13),
                     QgsPoint(12, 13),
                     QgsPoint(12, 15)])))
        layer.addItem(QgsAnnotationMarkerItem(QgsPoint(12, 13)))

        self.assertEqual(len(layer.items()), 3)
        layer.clear()
        self.assertEqual(len(layer.items()), 0)
Exemple #10
0
 def get_mesh_geometry(self, mesh, index):
     edge = mesh.edge(index)
     start_point = mesh.vertex(edge[0])
     end_point = mesh.vertex(edge[1])
     line = QgsLineString(start_point, end_point)
     return QgsGeometry(line)
Exemple #11
0
    def test_rendered_item_results_remove_outdated(self):
        """
        Test that outdated results are removed from rendered item result caches
        """
        canvas = QgsMapCanvas()
        canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        canvas.setFrameStyle(0)
        canvas.resize(600, 400)
        canvas.setCachingEnabled(True)
        self.assertEqual(canvas.width(), 600)
        self.assertEqual(canvas.height(), 400)

        layer = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())
        layer2 = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer2.isValid())

        item = QgsAnnotationPolygonItem(
            QgsPolygon(
                QgsLineString([
                    QgsPoint(11.5, 13),
                    QgsPoint(12, 13),
                    QgsPoint(12, 13.5),
                    QgsPoint(11.5, 13)
                ])))
        item.setSymbol(
            QgsFillSymbol.createSimple({
                'color': '200,100,100',
                'outline_color': 'black',
                'outline_width': '2'
            }))
        item.setZIndex(1)
        i1_id = layer.addItem(item)

        item = QgsAnnotationLineItem(
            QgsLineString(
                [QgsPoint(11, 13),
                 QgsPoint(12, 13),
                 QgsPoint(12, 15)]))
        item.setZIndex(2)
        i2_id = layer.addItem(item)

        item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
        item.setZIndex(3)
        i3_id = layer2.addItem(item)

        layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        layer2.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

        canvas.setLayers([layer, layer2])
        canvas.setExtent(QgsRectangle(10, 10, 18, 18))
        canvas.show()

        # need to wait until first redraw can occur (note that we first need to wait till drawing starts!)
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()

        results = canvas.renderedItemResults()
        self.assertCountEqual([i.itemId() for i in results.renderedItems()],
                              [i1_id, i2_id, i3_id])

        # now try modifying an annotation in the layer -- it will redraw, and we don't want to reuse any previously
        # cached rendered item results for this layer!

        item = QgsAnnotationPolygonItem(
            QgsPolygon(
                QgsLineString([
                    QgsPoint(11.5, 13),
                    QgsPoint(12.5, 13),
                    QgsPoint(12.5, 13.5),
                    QgsPoint(11.5, 13)
                ])))
        item.setZIndex(1)
        layer.replaceItem(i1_id, item)
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()

        item = QgsAnnotationMarkerItem(QgsPoint(17, 18))
        item.setZIndex(3)
        layer2.replaceItem(i3_id, item)
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()

        results = canvas.renderedItemResults()
        items_in_bounds = results.renderedAnnotationItemsInBounds(
            QgsRectangle(10, 10, 15, 15))
        self.assertCountEqual([i.itemId() for i in items_in_bounds],
                              [i1_id, i2_id])

        items_in_bounds = results.renderedAnnotationItemsInBounds(
            QgsRectangle(15, 15, 20, 20))
        self.assertCountEqual([i.itemId() for i in items_in_bounds], [i3_id])
Exemple #12
0
    def test_rendered_items(self):
        canvas = QgsMapCanvas()
        canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        canvas.setFrameStyle(0)
        canvas.resize(600, 400)
        canvas.setCachingEnabled(True)
        self.assertEqual(canvas.width(), 600)
        self.assertEqual(canvas.height(), 400)

        layer = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())
        layer2 = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer2.isValid())

        item = QgsAnnotationPolygonItem(
            QgsPolygon(
                QgsLineString([
                    QgsPoint(11.5, 13),
                    QgsPoint(12, 13),
                    QgsPoint(12, 13.5),
                    QgsPoint(11.5, 13)
                ])))
        item.setSymbol(
            QgsFillSymbol.createSimple({
                'color': '200,100,100',
                'outline_color': 'black',
                'outline_width': '2'
            }))
        item.setZIndex(1)
        i1_id = layer.addItem(item)

        item = QgsAnnotationLineItem(
            QgsLineString(
                [QgsPoint(11, 13),
                 QgsPoint(12, 13),
                 QgsPoint(12, 15)]))
        item.setZIndex(2)
        i2_id = layer.addItem(item)

        item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
        item.setZIndex(3)
        i3_id = layer2.addItem(item)

        layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        layer2.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

        canvas.setLayers([layer, layer2])
        canvas.setExtent(QgsRectangle(10, 10, 18, 18))
        canvas.show()

        # need to wait until first redraw can occur (note that we first need to wait till drawing starts!)
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()

        results = canvas.renderedItemResults()
        self.assertCountEqual([i.itemId() for i in results.renderedItems()],
                              [i1_id, i2_id, i3_id])

        # turn off a layer -- the other layer will be rendered direct from the cached version
        canvas.setLayers([layer2])
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()

        results = canvas.renderedItemResults()
        # only layer2 items should be present in results -- but these MUST be present while layer2 is visible in the canvas,
        # even though the most recent canvas redraw used a cached version of layer2 and didn't actually have to redraw the layer
        self.assertEqual([i.itemId() for i in results.renderedItems()],
                         [i3_id])

        # turn layer 1 back on
        canvas.setLayers([layer, layer2])
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()

        results = canvas.renderedItemResults()
        # both layer1 and layer2 items should be present in results -- even though NEITHER of these layers were re-rendered,
        # and instead we used precached renders of both layers
        self.assertCountEqual([i.itemId() for i in results.renderedItems()],
                              [i1_id, i2_id, i3_id])
    def test_merge_nodes(self):

        error_tolerance = 0.0001

        axial_lines = TestRCLCleaner.make_geometry_feature_layer(
            "LineString", [
                QgsLineString([
                    QgsPoint(535088.141198, 185892.128181),
                    QgsPoint(535037.617992, 186342.145327)
                ]),
                QgsLineString([
                    QgsPoint(534931.347277, 186103.472964),
                    QgsPoint(535285.548630, 186203.990233)
                ]),
                QgsLineString([
                    QgsPoint(534952.224080, 186285.463215),
                    QgsPoint(535248.881516, 185907.343107)
                ])
            ])

        unlinks = TestRCLCleaner.make_geometry_feature_layer("Point", [])

        # segment the axial lines without removing stubs
        stub_ratio = 0
        buffer = 1
        errors = True

        my_segmentor = segmentor(axial_lines, unlinks, stub_ratio, buffer,
                                 errors)

        my_segmentor.step = 10 / float(my_segmentor.layer.featureCount())
        my_segmentor.load_graph()
        # self.step specified in load_graph
        # progress emitted by break_segm & break_feats_iter
        cross_p_list = [
            my_segmentor.break_segm(feat) for feat in my_segmentor.list_iter(
                list(my_segmentor.feats.values()))
        ]
        my_segmentor.step = 20 / float(len(cross_p_list))
        segmented_feats = [
            my_segmentor.copy_feat(feat_geom_fid[0], feat_geom_fid[1],
                                   feat_geom_fid[2])
            for feat_geom_fid in my_segmentor.break_feats_iter(cross_p_list)
        ]

        segmented_geometry = [
            segmented_feat.geometry() for segmented_feat in segmented_feats
        ]
        segment_layer = TestRCLCleaner.make_geometry_feature_layer(
            "LineString", segmented_geometry)

        # segment the axial lines without removing stubs
        self.assertEqual(segment_layer.featureCount(), 9)

        # cleaning settings
        snap_threshold = 10  # TODO: Test
        break_at_vertices = True  # TODO: Test
        merge_type = 'intersections'  # TODO: Test
        # merge_type = 'colinear'  # TODO: Test
        collinear_threshold = 0  # TODO: Test
        angle_threshold = 10  # TODO: Test
        fix_unlinks = True  # TODO: Test
        orphans = True  # TODO: Test
        get_unlinks = True  # TODO: Test

        [
            load_range, cl1_range, cl2_range, cl3_range, break_range,
            merge_range, snap_range, unlinks_range, fix_range
        ] = RoadNetworkCleanerDialog.get_progress_ranges(
            break_at_vertices, merge_type, snap_threshold, get_unlinks,
            fix_unlinks)

        points = []
        multiparts = []
        pseudo_graph = sGraph({}, {})

        if break_at_vertices:

            pseudo_graph.step = load_range / float(
                segment_layer.featureCount())
            graph = sGraph({}, {})
            graph.total_progress = load_range
            pseudo_graph.load_edges_w_o_topology(
                clean_features_iter(segment_layer.getFeatures()))
            # QgsMessageLog.logMessage('pseudo_graph edges added %s' % load_range, level=Qgis.Critical)
            pseudo_graph.step = break_range / float(len(pseudo_graph.sEdges))
            graph.load_edges(
                pseudo_graph.break_features_iter(get_unlinks, angle_threshold,
                                                 fix_unlinks), angle_threshold)
            # QgsMessageLog.logMessage('pseudo_graph edges broken %s' % break_range, level=Qgis.Critical)

        else:
            graph = sGraph({}, {})
            graph.step = load_range / float(segment_layer.featureCount())
            graph.load_edges(clean_features_iter(segment_layer.getFeatures()),
                             angle_threshold)
            # QgsMessageLog.logMessage('graph edges added %s' % load_range, level=Qgis.Critical)

        graph.step = cl1_range / (float(len(graph.sEdges)) * 2.0)
        if orphans:
            graph.clean(True, False, snap_threshold, True)
        else:
            graph.clean(True, False, snap_threshold, False)
        # QgsMessageLog.logMessage('graph clean parallel and closed pl %s' % cl1_range, level=Qgis.Critical)

        if fix_unlinks:
            graph.step = fix_range / float(len(graph.sEdges))
            graph.fix_unlinks()
            # QgsMessageLog.logMessage('unlinks added  %s' % fix_range, level=Qgis.Critical)

        if snap_threshold != 0:

            graph.step = snap_range / float(len(graph.sNodes))
            graph.snap_endpoints(snap_threshold)
            # QgsMessageLog.logMessage('snap  %s' % snap_range, level=Qgis.Critical)
            graph.step = cl2_range / (float(len(graph.sEdges)) * 2.0)

            if orphans:
                graph.clean(True, False, snap_threshold, True)
            else:
                graph.clean(True, False, snap_threshold, False)
            # QgsMessageLog.logMessage('clean   %s' % cl2_range, level=Qgis.Critical)

        if merge_type == 'intersections':

            graph.step = merge_range / float(len(graph.sNodes))
            graph.merge_b_intersections(angle_threshold)
            # QgsMessageLog.logMessage('merge %s %s angle_threshold ' % (merge_range, angle_threshold),
            #                          level=Qgis.Critical)

        elif merge_type == 'collinear':

            graph.step = merge_range / float(len(graph.sEdges))
            graph.merge_collinear(collinear_threshold, angle_threshold)
            # QgsMessageLog.logMessage('merge  %s' % merge_range, level=Qgis.Critical)

        # cleaned multiparts so that unlinks are generated properly
        if orphans:
            graph.step = cl3_range / (float(len(graph.sEdges)) * 2.0)
            graph.clean(True, orphans, snap_threshold, False, True)
        else:
            graph.step = cl3_range / (float(len(graph.sEdges)) * 2.0)
            graph.clean(True, False, snap_threshold, False, True)

        if get_unlinks:
            graph.step = unlinks_range / float(len(graph.sEdges))
            graph.generate_unlinks()
            unlinks = graph.unlinks
        else:
            unlinks = []

        cleaned_features = [e.feature for e in list(graph.sEdges.values())]
        # add to errors multiparts and points
        graph.errors += multiparts
        graph.errors += points

        expected_segments = [
            QgsLineString([
                QgsPoint(535088.141198, 185892.128181),
                QgsPoint(535061.604423, 186143.502228)
            ]),
            QgsLineString([
                QgsPoint(535061.604423, 186143.502228),
                QgsPoint(535037.617992, 186342.145327)
            ]),
            QgsLineString([
                QgsPoint(534931.347277, 186103.472964),
                QgsPoint(535061.604423, 186143.502228)
            ]),
            QgsLineString([
                QgsPoint(535061.604423, 186143.502228),
                QgsPoint(535285.548630, 186203.990233)
            ]),
            QgsLineString([
                QgsPoint(534952.224080, 186285.463215),
                QgsPoint(535061.604423, 186143.502228)
            ]),
            QgsLineString([
                QgsPoint(535061.604423, 186143.502228),
                QgsPoint(535248.881516, 185907.343107)
            ])
        ]

        self.assertEqual(len(cleaned_features), len(expected_segments))

        for cleaned_feature in cleaned_features:
            cleaned_line = cleaned_feature.geometry().asPolyline()
            for expected_segment in expected_segments:
                x1eq = abs(cleaned_line[0].x() -
                           expected_segment[0].x()) < error_tolerance
                y1eq = abs(cleaned_line[0].y() -
                           expected_segment[0].y()) < error_tolerance
                x2eq = abs(cleaned_line[1].x() -
                           expected_segment[1].x()) < error_tolerance
                y2eq = abs(cleaned_line[1].y() -
                           expected_segment[1].y()) < error_tolerance
                if x1eq and y1eq and x2eq and y2eq:
                    expected_segments.remove(expected_segment)
                    break

        # all the expected features should have been found and removed
        self.assertEqual(len(expected_segments), 0)

        expected_errors = [
            QgsPoint(535060.304968, 186140.069309),
            QgsPoint(535059.304801, 186148.977932),
            QgsPoint(535065.203499, 186141.459442)
        ]

        self.assertEqual(len(graph.errors), len(expected_errors))

        for break_point_feat in graph.errors:
            break_point = break_point_feat.geometry().asPoint()
            for expected_break_point in expected_errors:
                xeq = abs(break_point.x() -
                          expected_break_point.x()) < error_tolerance
                yeq = abs(break_point.y() -
                          expected_break_point.y()) < error_tolerance
                if xeq and yeq:
                    expected_errors.remove(expected_break_point)
                    break

        # all the expected errors should have been found and removed
        self.assertEqual(len(expected_errors), 0)
Exemple #14
0
    def _correct_connections(self, line_points):
        """We prolong the lines in a case when the connection is not in normal angle"""
        i = 0
        previous_diff = 90
        while i < (len(line_points) - 3):
            diff = self._get_azimuth_diff(line_points[i], line_points[i + 1],
                                          line_points[i + 2])
            if not ((math.fabs(diff) > 85 and math.fabs(diff) < 95) or
                    (math.fabs(diff) > 265 and math.fabs(diff) < 275)):
                # The angle is not close to normal
                if i == 0:
                    # We are at the beginning and do not have previous diff, so we read next diff
                    # TODO possible change to detect diff according to engles of the area, better results
                    previous_diff = self._get_azimuth_diff(
                        line_points[2], line_points[3], line_points[4])
                distance_current = line_points[i].distance(line_points[i + 1])
                distance_next = line_points[i + 2].distance(line_points[i + 3])
                line_g = QgsGeometry.fromPolylineXY(
                    [line_points[i + 1], line_points[i + 2]])
                # hack - there is a problem of intersection on Windows - two lines that does not intersect
                # have intersection result close to 0 0, but in digits of e-300
                intersection_error_limit = 0.000000000001
                if distance_current > distance_next:
                    # we go from longer to shorter line
                    line = QgsLineString(QgsPoint(line_points[i + 2]),
                                         QgsPoint(line_points[i + 3]))
                    line.extend(distance_current, 0)
                    # We rotate the line segment to find cross with extended line
                    # The rotation is based on diff (rotate to be along extended line)
                    # and angle of the previous normal line
                    line_g.rotate(diff + (180 - previous_diff),
                                  line_points[i + 1])
                    line = QgsGeometry.fromWkt(line.asWkt())
                    intersection = line_g.intersection(line).centroid()
                    if not intersection.isNull():
                        intersection = intersection.asPoint()
                        # hack
                        if intersection.x(
                        ) > intersection_error_limit and intersection.y(
                        ) > intersection_error_limit:
                            line_points[i + 2] = intersection
                else:
                    # we go from shorter to longer line
                    line = QgsLineString(QgsPoint(line_points[i]),
                                         QgsPoint(line_points[i + 1]))
                    line.extend(0, distance_next)
                    line_g.rotate(diff + (180 - previous_diff),
                                  line_points[i + 2])
                    line = QgsGeometry.fromWkt(line.asWkt())
                    intersection = line_g.intersection(line).centroid()
                    if not intersection.isNull():
                        intersection = intersection.asPoint()
                        # hack
                        if intersection.x(
                        ) > intersection_error_limit and intersection.y(
                        ) > intersection_error_limit:
                            line_points[i + 1] = intersection
            i += 2
            previous_diff = diff

        return line_points
    def processAlgorithm(self, parameters, context, feedback):
        """
        RUN PROCESS
        """

        # READ NETWORK
        landxmlfn = self.parameterAsFile(parameters, self.INPUT, context)
        imp_net = landxml.network_from_xml(landxmlfn)
        networks = imp_net['networks']
        if 'epsg_code' in imp_net:
            crs = QgsCoordinateReferenceSystem('EPSG:' + imp_net['epsg_code'])
        else:
            crs = QgsCoordinateReferenceSystem('WKT:' + imp_net['wkt_crs'])

        # SHOW INFO
        feedback.pushInfo('=' * 40)
        feedback.pushInfo('CRS is {}'.format(crs.authid()))

        # GENERATE SINK LAYER
        newfields = QgsFields()
        newfields.append(QgsField("network", QVariant.String))
        newfields.append(QgsField("network_type", QVariant.String))
        newfields.append(QgsField("id", QVariant.String))
        newfields.append(QgsField("elev_sump", QVariant.Double))
        newfields.append(QgsField("elev_rim", QVariant.Double))
        newfields.append(QgsField("depth", QVariant.Double))
        (node_sink,
         node_id) = self.parameterAsSink(parameters, self.NODE_OUTPUT, context,
                                         newfields, QgsWkbTypes.Point, crs)

        newfields = QgsFields()
        newfields.append(QgsField("network", QVariant.String))
        newfields.append(QgsField("network_type", QVariant.String))
        newfields.append(QgsField("id", QVariant.String))
        newfields.append(QgsField("start", QVariant.String))
        newfields.append(QgsField("end", QVariant.String))
        newfields.append(QgsField("start_elv", QVariant.Double))
        newfields.append(QgsField("start_offset", QVariant.Double))
        newfields.append(QgsField("start_depth", QVariant.Double))
        newfields.append(QgsField("end_elv", QVariant.Double))
        newfields.append(QgsField("end_offset", QVariant.Double))
        newfields.append(QgsField("end_depth", QVariant.Double))
        newfields.append(QgsField("length", QVariant.Double))
        newfields.append(QgsField("slope", QVariant.Double))
        newfields.append(QgsField("sect_type", QVariant.String))
        newfields.append(QgsField("section", QVariant.String))
        (link_sink,
         link_id) = self.parameterAsSink(parameters, self.LINK_OUTPUT, context,
                                         newfields, QgsWkbTypes.LineString,
                                         crs)

        netcnt = nodcnt = lnkcnt = 0
        # ADD NETWORK
        for netname, network in networks.items():
            netcnt += 1
            net_type = network['net_type']
            # ADD NODES
            for nodename, node in network['nodes'].items():
                nodcnt += 1
                f = QgsFeature()
                point = QgsPoint(node['x'], node['y'])
                f.setGeometry(point)
                f.setAttributes([
                    netname, net_type, nodename, node['elev_sump'],
                    node['elev_rim'], node['depth']
                ])
                node_sink.addFeature(f)

            # ADD LINKS
            for linkname, link in network['links'].items():
                lnkcnt += 1
                g = QgsFeature()
                x = network['nodes'][link['start']]['x']
                y = network['nodes'][link['start']]['y']
                spoint = QgsPoint(x, y)
                x = network['nodes'][link['end']]['x']
                y = network['nodes'][link['end']]['y']
                epoint = QgsPoint(x, y)
                g.setGeometry(QgsGeometry(QgsLineString([spoint, epoint])))
                g.setAttributes([
                    netname, net_type, linkname, link['start'], link['end'],
                    link['start_elev'], link['start_offset'],
                    link['start_depth'], link['end_elev'], link['end_offset'],
                    link['end_depth'], link['length'], link['slope'],
                    link['sect_type'], link['section']
                ])
                link_sink.addFeature(g)

        # SHOW PROGRESS
        feedback.setProgress(100)  # Update the progress bar

        # SHOW INFO
        msg = 'LandXML Loaded successfully.'
        feedback.pushInfo(msg)
        msg = 'Added: {} networks.'.format(netcnt)
        feedback.pushInfo(msg)
        msg = 'Added: {} nodes.'.format(nodcnt)
        feedback.pushInfo(msg)
        msg = 'Added: {} links.'.format(lnkcnt)
        feedback.pushInfo(msg)
        feedback.pushInfo('=' * 40)

        # PROCCES CANCELED
        if feedback.isCanceled():
            return {}

        # OUTPUT
        return {self.NODE_OUTPUT: node_id, self.LINK_OUTPUT: link_id}
Exemple #16
0
    def processAlgorithm(self, parameters, context, feedback):
        hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
        vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
        hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
        vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)

        crs = self.parameterAsCrs(parameters, self.CRS, context)
        bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise QgsProcessingException(
                self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise QgsProcessingException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if width < hSpacing:
            raise QgsProcessingException(
                self.tr('Horizontal spacing is too small for the covered area'))

        if height < vSpacing:
            raise QgsProcessingException(
                self.tr('Vertical spacing is too small for the covered area'))

        fields = QgsFields()
        fields.append(QgsField('left', QVariant.Double, '', 24, 16))
        fields.append(QgsField('top', QVariant.Double, '', 24, 16))
        fields.append(QgsField('right', QVariant.Double, '', 24, 16))
        fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('coord', QVariant.Double, '', 24, 15))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.LineString, crs)

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            if feedback.isCanceled():
                break

            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(),
                                y,
                                bbox.xMaximum(),
                                y,
                                id,
                                y])
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            if feedback.isCanceled():
                break

            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x,
                                bbox.yMaximum(),
                                x,
                                bbox.yMinimum(),
                                id,
                                x])
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        return {self.OUTPUT: dest_id}
Exemple #17
0
    def processAlgorithm(self, progress):
        extent = self.getParameterValue(self.EXTENT).split(",")
        hSpacing = self.getParameterValue(self.HSPACING)
        vSpacing = self.getParameterValue(self.VSPACING)
        crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))

        bbox = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3]))

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise GeoAlgorithmExecutionException(self.tr("Invalid grid spacing: %s/%s" % (hSpacing, vSpacing)))

        if width < hSpacing:
            raise GeoAlgorithmExecutionException(self.tr("Horizontal spacing is too small for the covered area"))

        if height < vSpacing:
            raise GeoAlgorithmExecutionException(self.tr("Vertical spacing is too small for the covered area"))

        fields = [
            QgsField("left", QVariant.Double, "", 24, 16),
            QgsField("top", QVariant.Double, "", 24, 16),
            QgsField("right", QVariant.Double, "", 24, 16),
            QgsField("bottom", QVariant.Double, "", 24, 16),
            QgsField("id", QVariant.Int, "", 10, 0),
            QgsField("coord", QVariant.Double, "", 24, 15),
        ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, crs)

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPointV2(bbox.xMinimum(), y)
            pt2 = QgsPointV2(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(), y, bbox.xMaximum(), y, id, y])
            writer.addFeature(feat)
            y = y - vSpacing
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                progress.setPercentage(int(count / count_max * 50))

        progress.setPercentage(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPointV2(x, bbox.yMaximum())
            pt2 = QgsPointV2(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x, bbox.yMaximum(), x, bbox.yMinimum(), id, x])
            writer.addFeature(feat)
            x = x + hSpacing
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                progress.setPercentage(50 + int(count / count_max * 50))

        del writer
Exemple #18
0
    def testLineGenerationRelativeExtrusion(self):
        vl = QgsVectorLayer('LineStringZ?crs=EPSG:27700', 'lines', 'memory')
        self.assertTrue(vl.isValid())

        for line in ['LineStringZ(322006 129874 12, 322008 129910 13, 322038 129909 14, 322037 129868 15)',
                     'LineStringZ(322068 129900 16, 322128 129813 17)',
                     'LineStringZ(321996 129914 11, 321990 129896 15)',
                     'LineStringZ(321595 130176 1, 321507 130104 10)',
                     'LineStringZ(321558 129930 1, 321568 130029 10, 321516 130049 5)',
                     'LineStringZ(321603 129967 3, 321725 130042 9)']:
            f = QgsFeature()
            f.setGeometry(QgsGeometry.fromWkt(line))
            self.assertTrue(vl.dataProvider().addFeature(f))

        vl.elevationProperties().setClamping(Qgis.AltitudeClamping.Relative)
        vl.elevationProperties().setZScale(2.5)
        vl.elevationProperties().setZOffset(10)
        vl.elevationProperties().setExtrusionEnabled(True)
        vl.elevationProperties().setExtrusionHeight(7)

        curve = QgsLineString()
        curve.fromWkt(
            'LineString (-347692.88994020794052631 6632796.97473032586276531, -346576.99897185183363035 6632367.38372825458645821, -346396.02439485350623727 6632344.35087973903864622, -346374.34608158958144486 6632220.09952207934111357)')
        req = QgsProfileRequest(curve)
        req.setTransformContext(self.create_transform_context())

        rl = QgsRasterLayer(os.path.join(unitTestDataPath(), '3d', 'dtm.tif'), 'DTM')
        self.assertTrue(rl.isValid())
        terrain_provider = QgsRasterDemTerrainProvider()
        terrain_provider.setLayer(rl)
        terrain_provider.setScale(0.3)
        terrain_provider.setOffset(-5)
        req.setTerrainProvider(terrain_provider)

        req.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))

        generator = vl.createProfileGenerator(req)
        self.assertTrue(generator.generateProfile())
        results = generator.takeResults()

        if QgsProjUtils.projVersionMajor() >= 8:
            self.assertEqual(self.round_dict(results.distanceToHeightMap(), 1),
                             {675.2: 84.2, 1195.7: 86.8, 1223.1: 81.4, 1272.0: 90.0, 1339.4: 98.7, 1444.4: 100.0})
        else:
            self.assertEqual(self.round_dict(results.distanceToHeightMap(), 1),
                             {675.2: 80.5, 1195.7: 90.5, 1223.1: 87.4, 1272.0: 94.5, 1339.4: 98.0, 1444.4: 94.0})

        if QgsProjUtils.projVersionMajor() >= 8:
            self.assertCountEqual([g.asWkt(1) for g in results.asGeometries()],
                                  ['LineStringZ (-346549.8 6632363.9 81.4, -346549.8 6632363.9 88.4)',
                                   'LineStringZ (-346501.4 6632357.8 90, -346501.4 6632357.8 97)',
                                   'LineStringZ (-346434.5 6632349.2 98.7, -346434.5 6632349.2 105.7)',
                                   'LineStringZ (-346384.6 6632279.1 100, -346384.6 6632279.1 107)',
                                   'LineStringZ (-346577 6632367.4 86.8, -346577 6632367.4 93.8)',
                                   'LineStringZ (-347062.8 6632554.4 84.2, -347062.8 6632554.4 91.2)'])
            self.assertAlmostEqual(results.zRange().lower(), 81.3588, 2)
            self.assertAlmostEqual(results.zRange().upper(), 107.009, 2)
        else:
            self.assertCountEqual([g.asWkt(1) for g in results.asGeometries()],
                                  ['LineStringZ (-346549.8 6632363.9 87.4, -346549.8 6632363.9 94.4)',
                                   'LineStringZ (-346501.4 6632357.8 94.5, -346501.4 6632357.8 101.5)',
                                   'LineStringZ (-346434.5 6632349.2 98, -346434.5 6632349.2 105)',
                                   'LineStringZ (-346384.6 6632279.1 94, -346384.6 6632279.1 101)',
                                   'LineStringZ (-346577 6632367.4 90.5, -346577 6632367.4 97.5)',
                                   'LineStringZ (-347062.8 6632554.4 80.5, -347062.8 6632554.4 87.5)'])
            self.assertAlmostEqual(results.zRange().lower(), 80.45645, 2)
            self.assertAlmostEqual(results.zRange().upper(), 104.9811499, 2)
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

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

        QgsMessageLog.logMessage("-"*80)
        QgsMessageLog.logMessage(str(mvalue_exp))
        QgsMessageLog.logMessage(mvalue_exp.__class__.__name__)

        # instantiate the expression if mvalue is set
        if mvalue_exp:
            expression = QgsExpression(mvalue_exp)
            expression_ctx = self.createExpressionContext(parameters, context)
            expression.prepare(expression_ctx)
        else:
            expression = None

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

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

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

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

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

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

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

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

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

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

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

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

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

            linestring = QgsLineString(line)
            if mvalue_exp:
                linestring.addMValue(0)
                for i, node in enumerate(vertices):
                    QgsMessageLog.logMessage(node[2].__class__.__name__)
                    expression_ctx.setFeature(node[2])
                    mvalue = expression.evaluate(expression_ctx)
                    if expression.hasEvalError():
                        raise QgsProcessingException(
                            self.tr('Evaluation error: {0}').format(expression.evalErrorString()))
                    QgsMessageLog.logMessage("evaluating mvalue at {} to {} {}".format(i, mvalue, mvalue.__class__))
                    # mvalue = 12 # TODO : remove
                    QgsMessageLog.logMessage("setting mvalue at {} to {} {}".format(i, mvalue, mvalue.__class__))
                    linestring.setMAt(i, mvalue)
                    # test = linestring.mAt(i) # TODO : remove
                    # QgsMessageLog.logMessage("mvalue at {} is {} {}".format(i, test, test.__class__)) # TODO : remove
            f.setGeometry(QgsGeometry(linestring))
            sink.addFeature(f, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Exemple #20
0
    def testPolygonGenerationRelativeExtrusion(self):
        vl = QgsVectorLayer('PolygonZ?crs=EPSG:27700', 'lines', 'memory')
        self.assertTrue(vl.isValid())

        for line in [
            'PolygonZ ((321829.48893365426920354 129991.38697145861806348 1, 321847.89668515208177269 129996.63588572069420479 1, 321848.97131609614007175 129979.22330882755341008 1, 321830.31725845142500475 129978.07136809575604275 1, 321829.48893365426920354 129991.38697145861806348 1))',
            'PolygonZ ((321920.00953056826256216 129924.58260190498549491 2, 321924.65299345907988027 129908.43546159457764588 2, 321904.78543491888558492 129903.99811821122420952 2, 321900.80605239619035274 129931.39860145389684476 2, 321904.84799937985371798 129931.71552911199978553 2, 321908.93646715773502365 129912.90030360443051904 2, 321914.20495146053144708 129913.67693978428724222 2, 321911.30165811872575432 129923.01272751353099011 2, 321920.00953056826256216 129924.58260190498549491 2))',
            'PolygonZ ((321923.10517279652412981 129919.61521573827485554 3, 321922.23537852568551898 129928.3598982143739704 3, 321928.60423935484141111 129934.22530528216157109 3, 321929.39881197665818036 129923.29054521876969375 3, 321930.55804549407912418 129916.53248518184409477 3, 321923.10517279652412981 129919.61521573827485554 3))',
            'PolygonZ ((321990.47451346553862095 129909.63588680300745182 4, 321995.04325810901354998 129891.84052284323843196 4, 321989.66826330573530868 129890.5092018858413212 4, 321990.78512359503656626 129886.49917887404444627 4, 321987.37291929306229576 129885.64982962771318853 4, 321985.2254804756375961 129893.81317058412241749 4, 321987.63158903241856024 129894.41078495365218259 4, 321984.34022761805681512 129907.57450046355370432 4, 321990.47451346553862095 129909.63588680300745182 4))',
                'PolygonZ ((322103.03910495212767273 129795.91051736124791205 5, 322108.25568856322206557 129804.76113295342656784 5, 322113.29666162584908307 129803.9285887333098799 5, 322117.78645010641776025 129794.48194090687320568 5, 322103.03910495212767273 129795.91051736124791205 5))']:
            f = QgsFeature()
            f.setGeometry(QgsGeometry.fromWkt(line))
            self.assertTrue(vl.dataProvider().addFeature(f))

        vl.elevationProperties().setClamping(Qgis.AltitudeClamping.Relative)
        vl.elevationProperties().setZScale(2.5)
        vl.elevationProperties().setZOffset(10)
        vl.elevationProperties().setExtrusionEnabled(True)
        vl.elevationProperties().setExtrusionHeight(7)

        curve = QgsLineString()
        curve.fromWkt(
            'LineString (-347701.59207547508412972 6632766.96282589063048363, -346577.00878971704514697 6632369.7371364813297987, -346449.93654899462126195 6632331.81857067719101906, -346383.52035177784273401 6632216.85897350125014782)')
        req = QgsProfileRequest(curve)
        req.setTransformContext(self.create_transform_context())

        rl = QgsRasterLayer(os.path.join(unitTestDataPath(), '3d', 'dtm.tif'), 'DTM')
        self.assertTrue(rl.isValid())
        terrain_provider = QgsRasterDemTerrainProvider()
        terrain_provider.setLayer(rl)
        terrain_provider.setScale(0.3)
        terrain_provider.setOffset(-5)
        req.setTerrainProvider(terrain_provider)

        req.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))

        generator = vl.createProfileGenerator(req)
        self.assertTrue(generator.generateProfile())
        results = generator.takeResults()

        if QgsProjUtils.projVersionMajor() >= 8:
            self.assertEqual(self.round_dict(results.distanceToHeightMap(), 1),
                             {1041.8: 60.3, 1042.4: 60.2, 1049.5: 60.2, 1070.2: 60.2, 1073.1: 60.2, 1074.8: 60.3,
                              1078.9: 62.0, 1083.9: 62.0, 1091.1: 62.0, 1186.8: 59.3, 1189.8: 59.2, 1192.7: 59.2,
                              1199.2: 59.2, 1450.0: 65.5, 1455.6: 65.5, 1458.1: 65.5})
            self.assertAlmostEqual(results.zRange().lower(), 59.2499, 2)
            self.assertAlmostEqual(results.zRange().upper(), 72.50000, 2)
        else:
            self.assertEqual(self.round_dict(results.distanceToHeightMap(), 1),
                             {1041.8: 53.5, 1042.4: 53.5, 1049.5: 53.5, 1070.2: 53.5, 1073.1: 53.5, 1074.8: 53.5,
                              1078.9: 56.0, 1083.9: 56.0, 1091.1: 56.0, 1186.8: 62.3, 1189.8: 62.3, 1192.7: 62.3,
                              1199.2: 62.2, 1450.0: 67.0, 1455.6: 67.0, 1458.1: 67.0})
            self.assertAlmostEqual(results.zRange().lower(), 53.5, 2)
            self.assertAlmostEqual(results.zRange().upper(), 74.00000, 2)

        if QgsProjUtils.projVersionMajor() >= 8:
            self.assertCountEqual([g.asWkt(1) for g in results.asGeometries()],
                                  [
                                      'PolygonZ ((-346718.7 6632419.8 60.3, -346712 6632417.4 60.3, -346712 6632417.4 67.3, -346718.7 6632419.8 67.3, -346718.7 6632419.8 60.3))',
                                      'PolygonZ ((-346719.3 6632420 60.3, -346718.7 6632419.8 60.2, -346718.7 6632419.8 67.3, -346719.3 6632420 67.3, -346719.3 6632420 60.3))',
                                      'PolygonZ ((-346689.7 6632409.5 60.3, -346688.2 6632409 60.3, -346688.2 6632409 67.3, -346689.7 6632409.5 67.3, -346689.7 6632409.5 60.3))',
                                      'PolygonZ ((-346692.5 6632410.5 60.3, -346689.7 6632409.5 60.3, -346689.7 6632409.5 67.3, -346692.5 6632410.5 67.3, -346692.5 6632410.5 60.3))',
                                      'PolygonZ ((-346684.3 6632407.6 62, -346679.6 6632406 62, -346679.6 6632406 69, -346684.3 6632407.6 69, -346684.3 6632407.6 62))',
                                      'PolygonZ ((-346679.6 6632406 62, -346672.8 6632403.6 62, -346672.8 6632403.6 69, -346679.6 6632406 69, -346679.6 6632406 62))',
                                      'PolygonZ ((-346582.6 6632371.7 59.3, -346579.7 6632370.7 59.3, -346579.7 6632370.7 66.3, -346582.6 6632371.7 66.3, -346582.6 6632371.7 59.3))',
                                      'PolygonZ ((-346579.7 6632370.7 59.3, -346577 6632369.7 59.2, -346570.8 6632367.9 59.3, -346570.8 6632367.9 66.3, -346577 6632369.7 66.3, -346579.7 6632370.7 66.3, -346579.7 6632370.7 59.3))',
                                      'PolygonZ ((-346387.6 6632223.9 65.5, -346384.8 6632219 65.5, -346384.8 6632219 72.5, -346387.6 6632223.9 72.5, -346387.6 6632223.9 65.5))',
                                      'PolygonZ ((-346384.8 6632219 65.5, -346383.5 6632216.9 65.5, -346383.5 6632216.9 72.5, -346384.8 6632219 72.5, -346384.8 6632219 65.5))'])
        else:
            self.assertCountEqual([g.asWkt(1) for g in results.asGeometries()],
                                  [
                                      'PolygonZ ((-346718.7 6632419.8 53.5, -346712 6632417.4 53.5, -346712 6632417.4 60.5, -346718.7 6632419.8 60.5, -346718.7 6632419.8 53.5))',
                                      'PolygonZ ((-346719.3 6632420 53.5, -346718.7 6632419.8 53.5, -346718.7 6632419.8 60.5, -346719.3 6632420 60.5, -346719.3 6632420 53.5))',
                                      'PolygonZ ((-346689.7 6632409.5 53.5, -346688.2 6632409 53.5, -346688.2 6632409 60.5, -346689.7 6632409.5 60.5, -346689.7 6632409.5 53.5))',
                                      'PolygonZ ((-346692.5 6632410.5 53.5, -346689.7 6632409.5 53.5, -346689.7 6632409.5 60.5, -346692.5 6632410.5 60.5, -346692.5 6632410.5 53.5))',
                                      'PolygonZ ((-346684.3 6632407.6 56, -346679.6 6632406 56, -346679.6 6632406 63, -346684.3 6632407.6 63, -346684.3 6632407.6 56))',
                                      'PolygonZ ((-346679.6 6632406 56, -346672.8 6632403.6 56, -346672.8 6632403.6 63, -346679.6 6632406 63, -346679.6 6632406 56))',
                                      'PolygonZ ((-346582.6 6632371.7 62.3, -346579.7 6632370.7 62.3, -346579.7 6632370.7 69.3, -346582.6 6632371.7 69.3, -346582.6 6632371.7 62.3))',
                                      'PolygonZ ((-346579.7 6632370.7 62.3, -346577 6632369.7 62.3, -346570.8 6632367.9 62.3, -346570.8 6632367.9 69.3, -346577 6632369.7 69.3, -346579.7 6632370.7 69.3, -346579.7 6632370.7 62.3))',
                                      'PolygonZ ((-346387.6 6632223.9 67, -346384.8 6632219 67, -346384.8 6632219 74, -346387.6 6632223.9 74, -346387.6 6632223.9 67))',
                                      'PolygonZ ((-346384.8 6632219 67, -346383.5 6632216.9 67, -346383.5 6632216.9 74, -346384.8 6632219 74, -346384.8 6632219 67))'])
Exemple #21
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        RUN PROCESS
        """
        # INPUT
        slayer = self.parameterAsSource(parameters, self.SOURCE_INPUT, context)
        sfields = self.parameterAsFields(parameters, self.SOURCE_FIELDS, context)
        tlayer = self.parameterAsSource(parameters, self.TARGET_INPUT, context)

        # CHECK CRS
        crs = slayer.sourceCrs()
        if crs == tlayer.sourceCrs():

            # SEND INFORMATION TO THE USER
            feedback.pushInfo('='*40)
            feedback.pushInfo('CRS is {}'.format(crs.authid()))
        else:
            msg = 'ERROR: Layers have different CRS!'
            feedback.reportError(msg)
            return {}

        # OUTPUT LAYERS
        fields = QgsFields()
        fields.append(QgsField('source', QVariant.String))
        fields.append(QgsField('target', QVariant.String))
        for field in sfields:
            fields.append(QgsField(field, QVariant.Double))
        (assignment_sink, assignment_id) = self.parameterAsSink(
            parameters,
            self.ASSIGN_OUTPUT,
            context,
            fields,
            QgsWkbTypes.LineString,
            crs
            )

        fields = tlayer.fields()
        for field in sfields:
            fields.append(QgsField(field, QVariant.Double))
        (node_sink, node_id) = self.parameterAsSink(
            parameters,
            self.NODE_OUTPUT,
            context,
            fields,
            QgsWkbTypes.Point,
            crs
            )

        # ASSIGN, ACCUMULATE AND WRITE ASSIGNMENT LAYER
        values = {}
        for tfeature in tlayer.getFeatures():
            for field in sfields:
                values[(tfeature["id"], field)] = 0.0
        cnt = 0
        for sfeature in slayer.getFeatures():
            sxy = sfeature.geometry().asPoint()
            cdist = inf
            cfeature = None
            for tfeature in tlayer.getFeatures():
                dist = tfeature.geometry().asPoint().distance(sxy)
                if dist < cdist:
                    cdist = dist
                    cfeature = tfeature
            f = QgsFeature()
            spoint = QgsPoint(sxy)
            cpoint = QgsPoint(cfeature.geometry().asPoint())
            f.setGeometry(QgsLineString([spoint, cpoint]))
            attr = [sfeature["id"], cfeature["id"]]
            for field in sfields:
                attr.append(sfeature[field])
                values[(cfeature["id"], field)] += sfeature[field]
            f.setAttributes(attr)
            assignment_sink.addFeature(f)
            cnt += 1

            # SHOW PROGRESS
            feedback.setProgress(50*cnt/slayer.featureCount())

        # WRITE NODE LAYER
        cnt = 0
        for tfeature in tlayer.getFeatures():
            f = QgsFeature()
            attr = tfeature.attributes()
            for field in sfields:
                attr.append(values[(tfeature["id"], field)])
            f = tfeature
            f.setAttributes(attr)
            node_sink.addFeature(f)
            cnt += 1

            # SHOW PROGRESS
            feedback.setProgress(50+50*cnt/tlayer.featureCount())

        # SHOW PROGRESS
        feedback.pushInfo('Source #: {}.'.format(slayer.featureCount()))
        feedback.pushInfo('Target #: {}.'.format(tlayer.featureCount()))
        nncnt = sum((1 for x in values if abs(values[x]) > 0))
        feedback.pushInfo('Not null assignment #: {}.'.format(nncnt))
        feedback.pushInfo('='*40)

        # PROCCES CANCELED
        if feedback.isCanceled():
            return {}

        # OUTPUT
        return {self.ASSIGN_OUTPUT: assignment_id, self.NODE_OUTPUT: node_id}
Exemple #22
0
def processing(options, f, progressBar, progressMessage):
    '''
    Select trees which are on the contour of the forest and isolated trees.
    '''
    # Export Grid contour and isolated to crowns values
    forestSelectedPath = options['dst'] + 'tif/' + f + \
        '_forest_selected.tif'
    crownsPath = options['dst'] + 'shp/' + f + '_crowns.shp'
    # crownsStatsPath = options['dst'] + 'shp/' + f + '_crowns_stats.shp'
    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("gridstatisticsforpolygons started\n")
    fileTxt.close()

    crowns = QgsVectorLayer(crownsPath, "crowns", "ogr")
    inputStatRaster = QgsRasterLayer(forestSelectedPath, "forestSelected")
    z_stat = QgsZonalStatistics(crowns, inputStatRaster, '_', 1,
                                QgsZonalStatistics.Max)

    result_z_stat = z_stat.calculateStatistics(QgsFeedback())

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("gridstatisticsforpolygons passed\n")
    fileTxt.close()
    # crowns = QgsVectorLayer(crownsStatsPath, 'Crowns stats', 'ogr')
    crowns.selectByExpression('"_max"=1.0')
    selected_array = crowns.getValues("N", True)
    crowns.invertSelection()
    unselected_array = crowns.getValues("N", True)
    unselected_crowns_ids = crowns.getValues("$id", True)
    unselected_top_ids = crowns.getValues('"N" - 1', True)
    crowns.dataProvider().deleteFeatures(unselected_crowns_ids[0])

    treetopsPath = options['dst'] + 'shp/' + f + '_treetops.shp'
    treetops = QgsVectorLayer(treetopsPath, 'Tree tops', 'ogr')

    treetops.dataProvider().deleteFeatures(unselected_top_ids[0])

    treetopsSelectedPath = options['dst'] + 'shp/' + f + \
        '_treetops_selected.shp'
    crownsSelectedPath = options['dst'] + 'shp/' + f + '_crowns_selected.shp'
    treetopsTrianglesPath = options['dst'] + 'shp/' + f + \
        '_treetops_triangles.shp'

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("advancedpythonfieldcalculator started\n")
    fileTxt.close()

    treetops.dataProvider().addAttributes([QgsField('N', QVariant.Int)])
    treetops.updateFields()
    treetops.startEditing()
    for treetop in treetops.getFeatures():
        treetops.changeAttributeValue(treetop.id(),
                                      treetop.fieldNameIndex('N'),
                                      treetop.id())
    treetops.commitChanges()

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("joinattributesbylocation started\n")
    fileTxt.close()

    # Adapted from https://github.com/qgis/QGIS-Processing
    # TODO: replace by native QGIS c++ algo when available...

    crowns.dataProvider().addAttributes([QgsField('tid', QVariant.Int)])
    crowns.updateFields()
    crowns.startEditing()
    fcount = crowns.featureCount()
    counter = 0
    for crown in crowns.getFeatures():
        counter += 1
        progressBar.setValue(100 + int(counter * (600 / fcount)))
        progressMessage.setText('Joining crown ' + str(counter) + '/' +
                                str(fcount))
        request = QgsFeatureRequest()
        request.setFilterRect(crown.geometry().boundingBox())
        dp = treetops.dataProvider()
        for r in dp.getFeatures(request):
            if crown.geometry().intersects(r.geometry()):
                crowns.changeAttributeValue(crown.id(),
                                            crown.fieldNameIndex('tid'),
                                            r.id())
    crowns.commitChanges()

    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("delaunaytriangulation started\n")
    fileTxt.close()

    # delaunay triangulation Adapted from official Python plugin
    # TODO: replace by native QGIS c++ algo when available...

    fields = QgsFields()
    fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15))
    fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15))
    fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15))
    crs = QgsCoordinateReferenceSystem('EPSG:2056')
    triangleFile = QgsVectorFileWriter(treetopsTrianglesPath, 'utf-8', fields,
                                       QgsWkbTypes.Polygon, crs,
                                       'ESRI Shapefile')

    pts = []
    ptDict = {}
    ptNdx = -1
    c = voronoi.Context()
    features = treetops.getFeatures()
    total = 100.0 / treetops.featureCount() if treetops.featureCount() else 0
    progressMessage.setText('Starting triangulation...')
    for current, inFeat in enumerate(features):
        geom = QgsGeometry(inFeat.geometry())
        if geom.isNull():
            continue
        if geom.isMultipart():
            points = geom.asMultiPoint()
        else:
            points = [geom.asPoint()]
        for n, point in enumerate(points):
            x = point.x()
            y = point.y()
            pts.append((x, y))
            ptNdx += 1
            ptDict[ptNdx] = (inFeat.id(), n)
    progressMessage.setText('Triangulation step 1 ok')

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

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

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

        indices = list(triangle)
        indices.append(indices[0])
        polygon = []

        attrs = []
        step = 0
        for index in indices:
            fid, n = ptDict[ids[index]]
            request = QgsFeatureRequest().setFilterFid(fid)
            inFeat = next(treetops.getFeatures(request))
            geom = QgsGeometry(inFeat.geometry())
            point = QgsPoint(geom.asPoint())

            polygon.append(point)
            if step <= 3:
                attrs.append(ids[index])
            step += 1

        linestring = QgsLineString(polygon)
        poly = QgsPolygon()
        poly.setExteriorRing(linestring)
        feat.setAttributes(attrs)
        geometry = QgsGeometry().fromWkt(poly.asWkt())
        feat.setGeometry(geometry)
        triangleFile.addFeature(feat)
    progressMessage.setText('Triangulation terminated')

    #  Remove triangles with perimeter higher than threshold
    triangles = QgsVectorLayer(treetopsTrianglesPath, 'triangles', 'ogr')
    maxPeri = str(options['MaxTrianglePerimeter'])
    triangles.selectByExpression('$perimeter > ' + maxPeri)
    triangles_to_delete_ids = triangles.getValues("$id", True)
    triangles.dataProvider().deleteFeatures(triangles_to_delete_ids[0])

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("treeSelector passed\n")
    fileTxt.close()
    progressMessage.setText('Starting convexhull computing...')
Exemple #23
0
def UpdateBeamsData(packet, cornerPointUL, cornerPointUR, cornerPointLR,
                    cornerPointLL, ele):
    ''' Update Beams Values '''
    lat = packet.SensorLatitude
    lon = packet.SensorLongitude
    alt = packet.SensorTrueAltitude

    global groupName
    beamsLyr = qgsu.selectLayerByName(Beams_lyr, groupName)

    try:
        if all(v is not None for v in [
                beamsLyr, lat, lon, alt, cornerPointUL, cornerPointUR,
                cornerPointLR, cornerPointLL
        ]) and all(v >= 2 for v in [
                len(cornerPointUL),
                len(cornerPointUR),
                len(cornerPointLR),
                len(cornerPointLL)
        ]):
            beamsLyr.startEditing()
            if beamsLyr.featureCount() == 0:

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

            else:
                # UL
                beamsLyr.dataProvider().changeAttributeValues({
                    1: {
                        0: lon,
                        1: lat,
                        2: alt,
                        3: cornerPointUL[1],
                        4: cornerPointUL[0]
                    }
                })
                beamsLyr.dataProvider().changeGeometryValues({
                    1:
                    QgsGeometry(
                        QgsLineString(
                            QgsPoint(lon, lat, alt),
                            QgsPoint(cornerPointUL[1], cornerPointUL[0])))
                })
                # UR
                beamsLyr.dataProvider().changeAttributeValues({
                    2: {
                        0: lon,
                        1: lat,
                        2: alt,
                        3: cornerPointUR[1],
                        4: cornerPointUR[0]
                    }
                })
                beamsLyr.dataProvider().changeGeometryValues({
                    2:
                    QgsGeometry(
                        QgsLineString(
                            QgsPoint(lon, lat, alt),
                            QgsPoint(cornerPointUR[1], cornerPointUR[0])))
                })
                # LR
                beamsLyr.dataProvider().changeAttributeValues({
                    3: {
                        0: lon,
                        1: lat,
                        2: alt,
                        3: cornerPointLR[1],
                        4: cornerPointLR[0]
                    }
                })
                beamsLyr.dataProvider().changeGeometryValues({
                    3:
                    QgsGeometry(
                        QgsLineString(
                            QgsPoint(lon, lat, alt),
                            QgsPoint(cornerPointLR[1], cornerPointLR[0])))
                })
                # LL
                beamsLyr.dataProvider().changeAttributeValues({
                    4: {
                        0: lon,
                        1: lat,
                        2: alt,
                        3: cornerPointLL[1],
                        4: cornerPointLL[0]
                    }
                })
                beamsLyr.dataProvider().changeGeometryValues({
                    4:
                    QgsGeometry(
                        QgsLineString(
                            QgsPoint(lon, lat, alt),
                            QgsPoint(cornerPointLL[1], cornerPointLL[0])))
                })

            CommonLayer(beamsLyr)
            # 3D Style
            if ele:
                SetDefaultBeams3DStyle(beamsLyr)

    except Exception as e:
        qgsu.showUserAndLogMessage(
            QCoreApplication.translate("QgsFmvUtils",
                                       "Failed Update Beams Layer! : "),
            str(e))
    return
Exemple #24
0
    def processAlgorithm(self, parameters, context, feedback):
        ''' Here is where the processing itself takes place. '''
        #
        if not is_dependencies_satisfied:
            return {}

# Init
# The number of features in the input layer could be trimmed to user selection.
        the_layer = self.parameterAsSource(parameters, self.THE_LAYER, context)
        gok = QgsWkbTypes.geometryType(
            the_layer.wkbType()) == QgsWkbTypes.PointGeometry
        if the_layer is None or not gok:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.THE_LAYER))
        #
        bCHscal = self.parameterAsBool(parameters, self.BSCALE, context)
        if bCHscal:
            # Use another channel for scaling. All data from that channel will be used.
            scally = self.parameterAsSource(parameters, self.SCALLY, context)
            if scally is None or the_layer.wkbType() != QgsWkbTypes.Point:
                raise QgsProcessingException(
                    self.invalidSourceError(parameters, self.SCALLY))
        fidu_fld = self.parameterAsString(parameters, self.FID_FLD, context)
        data_fld = self.parameterAsString(parameters, self.DATA_FLD, context)
        line_fld = self.parameterAsString(parameters, self.LINE_FLD, context)
        invP = self.parameterAsBool(parameters, self.INVERTP, context)
        dumval = self.parameterAsDouble(parameters, self.DUMVAL, context)
        scale = self.parameterAsDouble(parameters, self.SCALE, context)
        offset = self.parameterAsDouble(parameters, self.OFFSET, context)
        join_to_line = self.parameterAsBool(parameters, self.JOINL, context)

        data = the_layer.fields().at(the_layer.fields().lookupField(data_fld))
        fidu = the_layer.fields().at(the_layer.fields().lookupField(fidu_fld))
        if not data.isNumeric() or not fidu.isNumeric():
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.THE_LAYER))

        line = the_layer.fields().at(the_layer.fields().lookupField(line_fld))
        data_ix = the_layer.fields().lookupField(data_fld)
        line_ix = the_layer.fields().lookupField(line_fld)
        fidu_ix = the_layer.fields().lookupField(fidu_fld)

        # Set output vector layer: point(X, Y, M) M is data value at that point
        output_wkb = QgsWkbTypes.LineString
        output_wkb = QgsWkbTypes.addM(output_wkb)

        # Fields of stacked profiles vector
        line_def = the_layer.fields().at(line_ix)
        fields = QgsFields()
        if line_def is not None:
            fields = QgsFields()
            fields.append(QgsField('Line', QVariant.String, '', 16))
            fields.append(QgsField('Type', QVariant.String, '', 2))
            fields.append(QgsField('NbPts', QVariant.Int, '', 10, 0))
            fields.append(QgsField('Azimuth', QVariant.Double, '', 10, 6))
            fields.append(QgsField('DistEP', QVariant.Double, '', 10, 2))
            fields.append(QgsField('Length', QVariant.Double, '', 10, 2))
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields, output_wkb,
                                               the_layer.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        # Get the features and fields of interest
        features = the_layer.getFeatures(
            QgsFeatureRequest().setSubsetOfAttributes(
                [fidu_ix, line_ix, data_ix]),
            QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)

        # CSV
        # Find min/max of data values for all lines and save each line in a csv file
        # Then process each line separately: can have any number of lines...
        lines = []
        xyzf = []
        lineN = ''
        nL = 0
        TL = 0.
        total = 60.0 / the_layer.featureCount() if the_layer.featureCount(
        ) else 0
        stat = QgsStatisticalSummary()
        for current, ft in enumerate(features):
            if feedback.isCanceled():
                break
            feedback.setProgress(int(current * total))
            if not ft.hasGeometry():
                continue
            #
            if ft[line.name()] != lineN:
                if xyzf != []:
                    lines.append([lineN, nL])
                    the_csv = os.path.join(self.tmpDir, '%s.csv' % str(lineN))
                    with codecs.open(the_csv, 'w', 'utf-8') as fo:
                        fo.write('X,Y,FID,Data\n')
                        for ar in xyzf:
                            fo.write(','.join(map(str, ar)))
                            fo.write('\n')
                    le = sqrt((xyzf[0][0] - xyzf[-1][0])**2 +
                              (xyzf[0][1] - xyzf[-1][1])**2)
                    if le > TL:
                        TL = le
                    xyzf = []
                    nL = 0
                lineN = ft[line.name()]
            #
            rdata = float(ft[data.name()])
            fiduu = int(ft[fidu.name()])
            if abs(rdata - dumval) < 1e-6:
                # Dummy value: skip
                continue
            #
            stat.addVariant(ft[data.name()])
            # how to handle QgsMultiPoint ???
            if (the_layer.wkbType() == QgsWkbTypes.MultiPoint
                    or the_layer.wkbType() == QgsWkbTypes.MultiPointM
                    or the_layer.wkbType() == QgsWkbTypes.MultiPointZ
                    or the_layer.wkbType() == QgsWkbTypes.MultiPointZM
                    or the_layer.wkbType() == QgsWkbTypes.MultiPoint25D):
                # Suppose they all have the same attributes:
                #  in this case it seems useless to get more than the first point, but...
                points = ft.geometry().constGet().clone()
            else:
                points = [ft.geometry().constGet().clone()]
            try:
                for point in points:
                    xyzf.append([point.x(), point.y(), fiduu, rdata])
                    nL += 1
            except:
                pass
        # last line
        if xyzf != []:
            lines.append([lineN, nL])
            the_csv = os.path.join(self.tmpDir, '%s.csv' % str(lineN))
            with codecs.open(the_csv, 'w', 'utf-8') as fo:
                fo.write('X,Y,FID,Data\n')
                for ar in xyzf:
                    fo.write(','.join(map(str, ar)))
                    fo.write('\n')
            le = sqrt((xyzf[0][0] - xyzf[-1][0])**2 +
                      (xyzf[0][1] - xyzf[-1][1])**2)
            if le > TL:
                TL = le
        #
        stat.finalize()
        self.dmean = stat.mean()
        self.mult = TL / (stat.max() - stat.min())
        #
        if bCHscal:
            # Scaling field: retrieve its stats
            scch_fld = self.parameterAsString(parameters, self.SCALCH, context)
            scch = scally.fields().at(scally.fields().lookupField(scch_fld))
            scch_ix = scally.fields().lookupField(scch_fld)
            scch_f = scally.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([scch_ix]),
                QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
            stat = QgsStatisticalSummary()
            for current, ft in enumerate(scch_f):
                stat.addVariant(ft[scch.name()])
            stat.finalize()
            self.dmean = stat.mean()
            self.mult = TL / (stat.max() - stat.min())
        #
        if invP:
            iv = -1
        else:
            iv = 1

# Profile
        total = 40.0 / (len(lines) + 1)
        # For each line:
        for current, z in enumerate(lines):
            line = z[0]
            if feedback.isCanceled():
                break
            if not ft.hasGeometry():
                continue
            feedback.setProgress(int(current * total) + 60.)

            # Read line back from csv
            the_csv = os.path.join(self.tmpDir, '%s.csv' % str(line))
            if not os.path.exists(the_csv):
                raise ValueError(
                    'It seems parameters are swaped: LINE <-> DATA!')

            ar = pd.read_csv(the_csv)
            ar = ar.sort_values('FID')

            # Create the profile
            px, py = self._do_profile(ar, iv, scale, offset)

            #Construct vector layer
            f = QgsFeature()
            typeL = str(self.type)
            azimut = float(self.azimut)
            Len = float(self.length)
            CLen = float(self.clength)
            f.setAttributes(
                [str(line), typeL,
                 int(len(px)), azimut, Len, CLen])
            line_pts = [
                QgsPoint(x, y, m=m) for x, y, m in zip(px, py, ar.Data)
            ]
            if join_to_line:
                # Join profile to its line
                e = len(ar) - 1
                ar0 = [QgsPoint(ar.X[0], ar.Y[0], m=0.)]
                ar1 = [QgsPoint(ar.X[e], ar.Y[e], m=0.)]
                line_pts = ar0 + line_pts + ar1
            #
            f.setGeometry(QgsGeometry(QgsLineString(line_pts)))
            sink.addFeature(f, QgsFeatureSink.FastInsert)
            # Delete temp csv file
            try:
                os.remove(the_csv)
            except:
                pass

        return {self.OUTPUT: dest_id}
Exemple #25
0
    def test_merge_nodes(self):

        error_tolerance = 0.0001

        vl = TestNetworkSegmenter.make_geometry_feature_layer(
            "LineString", [
                QgsLineString([
                    QgsPoint(535088.141198, 185892.128181),
                    QgsPoint(535037.617992, 186342.145327)
                ]),
                QgsLineString([
                    QgsPoint(535012.560937, 186126.546603),
                    QgsPoint(535285.548630, 186203.990233)
                ]),
                QgsLineString([
                    QgsPoint(534952.224080, 186285.463215),
                    QgsPoint(535248.881516, 185907.343107)
                ])
            ])

        ul = TestNetworkSegmenter.make_geometry_feature_layer(
            "Point",
            [
                QgsPoint(535067.772756, 186147.054373),  # invalid unlink
                QgsPoint(535059.304801, 186148.977932)  # valid unlink
            ])

        self.assertEqual(vl.featureCount(), 3)

        # segment the axial lines without removing stubs
        stub_ratio = 0.3
        buffer = 1
        errors = True

        my_segmentor = segmentor(vl, ul, stub_ratio, buffer, errors)

        break_point_feats, invalid_unlink_point_feats, stubs_point_feats, segmented_feats = [], [], [], []

        my_segmentor.step = 10 / float(my_segmentor.layer.featureCount())
        my_segmentor.load_graph()
        # self.step specified in load_graph
        # progress emitted by break_segm & break_feats_iter
        cross_p_list = [
            my_segmentor.break_segm(feat) for feat in my_segmentor.list_iter(
                list(my_segmentor.feats.values()))
        ]
        my_segmentor.step = 20 / float(len(cross_p_list))
        segmented_feats = [
            my_segmentor.copy_feat(feat_geom_fid[0], feat_geom_fid[1],
                                   feat_geom_fid[2])
            for feat_geom_fid in my_segmentor.break_feats_iter(cross_p_list)
        ]

        if errors:
            cross_p_list = set(
                list(itertools.chain.from_iterable(cross_p_list)))

            ids1 = [i for i in range(0, len(cross_p_list))]
            break_point_feats = [
                my_segmentor.copy_feat(my_segmentor.break_f,
                                       QgsGeometry.fromPointXY(p_fid[0]),
                                       p_fid[1])
                for p_fid in (list(zip(cross_p_list, ids1)))
            ]
            ids2 = [
                i for i in range(
                    max(ids1) + 1,
                    max(ids1) + 1 + len(my_segmentor.invalid_unlinks))
            ]
            invalid_unlink_point_feats = [
                my_segmentor.copy_feat(my_segmentor.invalid_unlink_f,
                                       QgsGeometry.fromPointXY(p_fid1[0]),
                                       p_fid1[1])
                for p_fid1 in (list(zip(my_segmentor.invalid_unlinks, ids2)))
            ]
            ids = [
                i for i in range(
                    max(ids1 + ids2) + 1,
                    max(ids1 + ids2) + 1 + len(my_segmentor.stubs_points))
            ]
            stubs_point_feats = [
                my_segmentor.copy_feat(my_segmentor.stub_f,
                                       QgsGeometry.fromPointXY(p_fid2[0]),
                                       p_fid2[1])
                for p_fid2 in (list(zip(my_segmentor.stubs_points, ids)))
            ]

        expected_segments = [
            QgsLineString([
                QgsPoint(535088.141198, 185892.128181),
                QgsPoint(535060.302601, 186140.090392)
            ]),
            QgsLineString([
                QgsPoint(535060.302601, 186140.090392),
                QgsPoint(535037.617991, 186342.145327)
            ]),
            QgsLineString([
                QgsPoint(535060.302601, 186140.090392),
                QgsPoint(535065.189841, 186141.476849)
            ]),
            QgsLineString([
                QgsPoint(535065.189841, 186141.476849),
                QgsPoint(535285.548629, 186203.990232)
            ]),
            QgsLineString([
                QgsPoint(534952.224079, 186285.463214),
                QgsPoint(535065.189841, 186141.476849)
            ]),
            QgsLineString([
                QgsPoint(535065.189841, 186141.476849),
                QgsPoint(535248.881516, 185907.343106)
            ]),
        ]

        self.assertEqual(len(segmented_feats), len(expected_segments))

        for segmented_feat in segmented_feats:
            segmented_line = segmented_feat.geometry().asPolyline()
            for expected_segment in expected_segments:
                x1eq = abs(segmented_line[0].x() -
                           expected_segment[0].x()) < error_tolerance
                y1eq = abs(segmented_line[0].y() -
                           expected_segment[0].y()) < error_tolerance
                x2eq = abs(segmented_line[1].x() -
                           expected_segment[1].x()) < error_tolerance
                y2eq = abs(segmented_line[1].y() -
                           expected_segment[1].y()) < error_tolerance
                if x1eq and y1eq and x2eq and y2eq:
                    expected_segments.remove(expected_segment)
                    break

        # all the expected features should have been found and removed
        self.assertEqual(len(expected_segments), 0)

        expected_break_points = [
            QgsPoint(535285.548629, 186203.990232),
            QgsPoint(535065.189841, 186141.476849),
            QgsPoint(535060.302601, 186140.090392),
            QgsPoint(535037.617991, 186342.145327),
            QgsPoint(534952.224079, 186285.463214),
            QgsPoint(535248.881516, 185907.343106),
            QgsPoint(535088.141198, 185892.128181)
        ]

        self.assertEqual(len(break_point_feats), len(expected_break_points))

        for break_point_feat in break_point_feats:
            break_point = break_point_feat.geometry().asPoint()
            for expected_break_point in expected_break_points:
                xeq = abs(break_point.x() -
                          expected_break_point.x()) < error_tolerance
                yeq = abs(break_point.y() -
                          expected_break_point.y()) < error_tolerance
                if xeq and yeq:
                    expected_break_points.remove(expected_break_point)
                    break

        # all the expected break points should have been found and removed
        self.assertEqual(len(expected_segments), 0)

        # only one stub removed
        self.assertEqual(len(stubs_point_feats), 1)
        self.assertAlmostEqual(stubs_point_feats[0].geometry().asPoint().x(),
                               535012.560936,
                               places=3)
        self.assertAlmostEqual(stubs_point_feats[0].geometry().asPoint().y(),
                               186126.546602,
                               places=3)

        # first unlink is invalid
        self.assertEqual(len(invalid_unlink_point_feats), 1)
        self.assertAlmostEqual(
            invalid_unlink_point_feats[0].geometry().asPoint().x(),
            next(ul.getFeatures()).geometry().asPoint().x(),
            places=3)
        self.assertAlmostEqual(
            invalid_unlink_point_feats[0].geometry().asPoint().y(),
            next(ul.getFeatures()).geometry().asPoint().y(),
            places=3)
 def get_mesh_geometry(self, mesh, index):
     face = mesh.face(index)
     points = [mesh.vertex(v) for v in face]
     polygon = QgsPolygon()
     polygon.setExteriorRing(QgsLineString(points))
     return QgsGeometry(polygon)
Exemple #27
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context)
        order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context)
        text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context)

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

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

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

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

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

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

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

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

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

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

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

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

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

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

        return {self.OUTPUT: dest_id}
    def createGeom(self, coords):

        crsDest = self.__layer.crs()

        rc = ReprojectCoordinates(self.crsId, crsDest.srsid(), self.__hasZ, self.__hasM)
        if self.crsId != crsDest.srsid():
            coordsPoint = list(rc.reproject(coords, True))
        else:
            coordsPoint = list(rc.copyCoordstoPoints(coords))

        # Point and multipoint Geometry
        # Always 1 part, 0 element of matrix
        if self.__layergeometryType == QgsWkbTypes.PointGeometry:
            if self.__isMultiType:
                multipoint = QgsMultiPoint()
                for coords_item in coordsPoint[0][1]:
                    multipoint.addGeometry(coords_item)

                geom = QgsGeometry(multipoint)
                self.createFeature(geom)
            else:
                geom = QgsGeometry(coordsPoint[0][1][0])
                self.createFeature(geom)

        elif self.__layergeometryType == QgsWkbTypes.LineGeometry:
            if self.__isMultiType:
                multiline = QgsGeometry(QgsMultiLineString())
                for j in range(len(coordsPoint)):
                    line = QgsLineString(coordsPoint[j][1])
                    multiline.addPart(line)
                self.createFeature(multiline)
            else:
                line = QgsGeometry(QgsLineString(coordsPoint[0][1]))
                self.createFeature(line)

        elif self.__layergeometryType == QgsWkbTypes.PolygonGeometry:
            if self.__isMultiType:
                multipoly = QgsGeometry(QgsMultiPolygon())

                for i in range(len(coordsPoint)):
                    if int(coordsPoint[i][0]) > 0:
                        mycurve = QgsLineString(coordsPoint[i][1])
                        poly = QgsPolygon()
                        poly.setExteriorRing(mycurve)

                        polyGeometry = QgsGeometry(QgsPolygon(poly))
                        for j in range(len(coordsPoint)):
                            if int(coordsPoint[j][0]) < 0:
                                containsAllPoints = True
                                for k in range(len(coordsPoint[j][1])):
                                    containsAllPoints = True
                                    curPoint = coordsPoint[j][1][k].clone()
                                    containsAllPoints = containsAllPoints \
                                                    and polyGeometry.contains(QgsPointXY(curPoint.x(), curPoint.y()))
                                if containsAllPoints:
                                    mycurve = QgsLineString(coordsPoint[j][1])
                                    poly.addInteriorRing(mycurve)

                        multipoly.addPart(poly)
                self.createFeature(multipoly)
            else:
                extRing = 0
                for i in range(len(coordsPoint)):
                    if int(coordsPoint[i][0]) > 0:
                       extRing = i

                mycurve = QgsLineString(coordsPoint[extRing][1])
                poly = QgsPolygon()
                poly.setExteriorRing(mycurve)

                polyGeometry = QgsGeometry(QgsPolygon(poly))

                for i in range(len(coordsPoint)):
                    if int(coordsPoint[i][0]) < 0:
                        containsAllPoints = True
                        for j in range(len(coordsPoint[i][1])):
                            containsAllPoints = True
                            curPoint = coordsPoint[i][1][j].clone()
                            containsAllPoints = containsAllPoints \
                                                and polyGeometry.contains(QgsPointXY(curPoint.x(), curPoint.y()))
                        if containsAllPoints:
                            mycurve = QgsLineString(coordsPoint[i][1])
                            poly.addInteriorRing(mycurve)
                        else:
                            QMessageBox.question(self.iface.mainWindow(),
                                                 self.translate_str("Ring not in exterior contour"),
                                                 self.translate_str("The new geometry of the feature"
                                                                    " isn't valid. Do you want to use it anyway?"),
                                                 QMessageBox.Yes, QMessageBox.No)

                self.createFeature(QgsGeometry(poly))
Exemple #29
0
    def processAlgorithm(self, parameters, context, feedback):
        hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
        vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
        hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
        vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)

        bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
        crs = self.parameterAsCrs(parameters, self.CRS, context)

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise QgsProcessingException(
                self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise QgsProcessingException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if width < hSpacing:
            raise QgsProcessingException(
                self.tr('Horizontal spacing is too small for the covered area'))

        if height < vSpacing:
            raise QgsProcessingException(
                self.tr('Vertical spacing is too small for the covered area'))

        fields = QgsFields()
        fields.append(QgsField('left', QVariant.Double, '', 24, 16))
        fields.append(QgsField('top', QVariant.Double, '', 24, 16))
        fields.append(QgsField('right', QVariant.Double, '', 24, 16))
        fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('coord', QVariant.Double, '', 24, 15))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.LineString, crs)

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            if feedback.isCanceled():
                break

            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(),
                                y,
                                bbox.xMaximum(),
                                y,
                                id,
                                y])
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            if feedback.isCanceled():
                break

            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x,
                                bbox.yMaximum(),
                                x,
                                bbox.yMinimum(),
                                id,
                                x])
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        return {self.OUTPUT: dest_id}
Exemple #30
0
    def processAlgorithm(self, parameters, context, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        hSpacing = self.getParameterValue(self.HSPACING)
        vSpacing = self.getParameterValue(self.VSPACING)
        hOverlay = self.getParameterValue(self.HOVERLAY)
        vOverlay = self.getParameterValue(self.VOVERLAY)
        crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if width < hSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Horizontal spacing is too small for the covered area'))

        if height < vSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Vertical spacing is too small for the covered area'))

        fields = QgsFields()
        fields.append(QgsField('left', QVariant.Double, '', 24, 16))
        fields.append(QgsField('top', QVariant.Double, '', 24, 16))
        fields.append(QgsField('right', QVariant.Double, '', 24, 16))
        fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('coord', QVariant.Double, '', 24, 15))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, crs, context)

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(),
                                y,
                                bbox.xMaximum(),
                                y,
                                id,
                                y])
            writer.addFeature(feat, QgsFeatureSink.FastInsert)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x,
                                bbox.yMaximum(),
                                x,
                                bbox.yMinimum(),
                                id,
                                x])
            writer.addFeature(feat, QgsFeatureSink.FastInsert)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        del writer
Exemple #31
0
 def testQgsLineStringRepr(self):
     ls = QgsLineString([QgsPoint(10, 2), QgsPoint(10, 1), QgsPoint(5, 1)])
     self.assertEqual(ls.__repr__(), '<QgsLineString: LineString (10 2, 10 1, 5 1)>')
    def processAlgorithmOutput(self, results, parameters, context, feedback):
        output_fields = QgsFields()
        result_type = self.RESULT_TYPE[self.params["OUTPUT_RESULT_TYPE"]]
        if result_type == "NORMAL":
            output_fields.append(QgsField("search_id", QVariant.String, "text", 255))
            output_fields.append(QgsField("location_id", QVariant.String, "text", 255))
            output_fields.append(QgsField("travel_time", QVariant.Double, "text", 255))
            output_fields.append(QgsField("distance", QVariant.Double, "text", 255))
            output_fields.append(
                QgsField("departure_time", QVariant.String, "text", 255)
            )
            output_fields.append(QgsField("arrival_time", QVariant.String, "text", 255))
        else:
            output_fields.append(QgsField("type", QVariant.String, "text", 255))
            output_fields.append(QgsField("mode", QVariant.String, "text", 255))
            output_fields.append(QgsField("directions", QVariant.String, "text", 255))

        output_crs = EPSG4326
        output_type = QgsWkbTypes.LineString

        (sink, sink_id) = self.parameterAsSink(
            parameters, "OUTPUT", context, output_fields, output_type, output_crs
        )

        for result in results:
            for location in result["locations"]:

                if result_type == "NORMAL":

                    # Create the geom
                    geom = QgsLineString()
                    for part in location["properties"][0]["route"]["parts"]:
                        for coord in part["coords"]:
                            point = QgsPoint(coord["lng"], coord["lat"])
                            if geom.endPoint() != point:
                                geom.addVertex(point)

                    # Create the feature
                    feature = QgsFeature(output_fields)
                    feature.setGeometry(geom)
                    feature.setAttribute(0, result["search_id"])
                    feature.setAttribute(1, location["id"])
                    feature.setAttribute(2, location["properties"][0]["travel_time"])
                    feature.setAttribute(3, location["properties"][0]["distance"])
                    feature.setAttribute(
                        4, location["properties"][0]["route"]["departure_time"]
                    )
                    feature.setAttribute(
                        5, location["properties"][0]["route"]["arrival_time"]
                    )
                    sink.addFeature(feature, QgsFeatureSink.FastInsert)
                else:
                    for part in location["properties"][0]["route"]["parts"]:

                        # Create the geom
                        geom = QgsLineString()
                        for coord in part["coords"]:
                            point = QgsPoint(coord["lng"], coord["lat"])
                            geom.addVertex(point)

                        # Create the feature
                        feature_d = QgsFeature(output_fields)
                        feature_d.setGeometry(geom)
                        feature_d.setAttribute(0, part["type"])
                        feature_d.setAttribute(1, part["mode"])
                        feature_d.setAttribute(2, part["directions"])
                        sink.addFeature(feature_d, QgsFeatureSink.FastInsert)

        feedback.pushDebugInfo("TimeFilterAlgorithm done !")

        # to get hold of the layer in post processing
        self.sink_id = sink_id

        return {"OUTPUT": sink_id}
Exemple #33
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        close_path = self.parameterAsBool(parameters, self.CLOSE_PATH, context)
        group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD,
                                                  context)
        order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD,
                                                  context)
        order_expression = self.parameterAsString(parameters,
                                                  self.ORDER_EXPRESSION,
                                                  context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT,
                                             context)
        text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR,
                                          context)

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

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

        if order_field_name:
            order_expression = QgsExpression.quotedColumnRef(order_field_name)

        if not order_expression:
            raise QgsProcessingException(
                self.tr('ORDER_EXPRESSION parameter is missing.'))

        expression_context = self.createExpressionContext(
            parameters, context, source)
        expression = QgsExpression(order_expression)
        if expression.hasParserError():
            raise QgsProcessingException(expression.parserErrorString())
        expression.prepare(expression_context)
        order_field_type = QVariant.String
        if expression.isField():
            field_name = next(iter(expression.referencedColumns()))
            order_field_type = source.fields().field(field_name).type()

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

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

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

        points = dict()
        required_fields = expression.referencedColumns()
        required_fields.add(group_field_name)
        features = source.getFeatures(
            QgsFeatureRequest().setSubsetOfAttributes(required_fields,
                                                      source.fields()),
            QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

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

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

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

            if close_path is True:
                if line[0] != line[-1]:
                    line.append(line[0])

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

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

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

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

        return {self.OUTPUT: dest_id}
Exemple #34
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        outer_col = self.parameterAsString(parameters,
                                           self.PrmOuterRadiusField, context)
        inner_col = self.parameterAsString(parameters,
                                           self.PrmInnerRadiusField, context)
        lines_col = self.parameterAsString(parameters,
                                           self.PrmNumberOfLinesField, context)
        def_outer_radius = self.parameterAsDouble(parameters,
                                                  self.PrmDefaultOuterRadius,
                                                  context)
        def_inner_radius = self.parameterAsDouble(parameters,
                                                  self.PrmDefaultInnerRadius,
                                                  context)
        def_lines = self.parameterAsDouble(parameters,
                                           self.PrmDefaultNumberOfLines,
                                           context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                    context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        measure_factor = conversionToMeters(units)

        def_inner_radius *= measure_factor
        def_outer_radius *= 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))
        (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                               context, fields,
                                               QgsWkbTypes.MultiLineString,
                                               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:
                line_strings = []
                pt = feature.geometry().asPoint()
                pt_orig = QgsPoint(pt)
                # 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 inner_col:
                    inner_radius = float(feature[inner_col]) * measure_factor
                else:
                    inner_radius = def_inner_radius
                if outer_col:
                    outer_radius = float(feature[outer_col]) * measure_factor
                else:
                    outer_radius = def_outer_radius
                if lines_col:
                    num_lines = int(feature[lines_col])
                else:
                    num_lines = def_lines
                if num_lines <= 0:
                    num_bad += 1
                    continue
                angle = 0
                angle_step = 360.0 / num_lines
                while angle < 360:
                    if inner_radius == 0:
                        pt_start = pt_orig
                    else:
                        g = geod.Direct(lat, lon, angle, inner_radius,
                                        Geodesic.LATITUDE | Geodesic.LONGITUDE)
                        pt_start = QgsPoint(g['lon2'], g['lat2'])
                        if src_crs != epsg4326:
                            pt_start = to_sink_crs.transform(pt_start)
                    g = geod.Direct(lat, lon, angle, outer_radius,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pt_end = QgsPoint(g['lon2'], g['lat2'])
                    if src_crs != epsg4326:
                        pt_end = to_sink_crs.transform(pt_end)

                    line_str = QgsLineString([pt_start, pt_end])
                    line_strings.append(line_str)
                    angle += angle_step

                f = QgsFeature()
                if len(line_strings) == 1:
                    f.setGeometry(QgsGeometry(line_strings[0]))
                else:
                    g = QgsMultiLineString()
                    for line_str in line_strings:
                        g.addGeometry(line_str)
                    f.setGeometry(QgsGeometry(g))
                attr = feature.attributes()
                if export_geom:
                    attr.append(pt_orig.x())
                    attr.append(pt_orig.y())
                f.setAttributes(attr)
                sink.addFeature(f)
            except Exception:
                s = traceback.format_exc()
                feedback.pushInfo(s)
                num_bad += 1

            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}
Exemple #35
0
    def testJSONExporter(self):
        """ test converting features to GeoJSON """
        fields = QgsFields()
        fields.append(QgsField("name", QVariant.String))
        fields.append(QgsField("cost", QVariant.Double))
        fields.append(QgsField("population", QVariant.Int))

        feature = QgsFeature(fields, 5)
        feature.setGeometry(QgsGeometry(QgsPointV2(5, 6)))
        feature.setAttributes(['Valsier Peninsula', 6.8, 198])

        exporter = QgsJSONExporter()

        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test with linestring for bbox inclusion
        l = QgsLineString()
        l.setPoints([QgsPointV2(5, 6), QgsPointV2(15, 16)])
        feature.setGeometry(QgsGeometry(QgsLineString(l)))

        expected = """{
   "type":"Feature",
   "id":5,
   "bbox":[5, 6, 15, 16],
   "geometry":
   {"type": "LineString", "coordinates": [ [5, 6], [15, 16]]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test that precision is respected
        feature.setGeometry(QgsGeometry(QgsPointV2(5.444444444, 6.333333333)))
        exporter.setPrecision(3)
        self.assertEqual(exporter.precision(), 3)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5.444, 6.333]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        feature.setGeometry(QgsGeometry(QgsPointV2(5, 6)))
        exporter.setPrecision(17)

        # test that attribute subset is respected
        exporter.setAttributes([0, 2])
        self.assertEqual(exporter.attributes(), [0, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setAttributes([1])
        self.assertEqual(exporter.attributes(), [1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "cost":6.8
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setAttributes([])

        # text excluding attributes

        exporter.setExcludedAttributes([1])
        self.assertEqual(exporter.excludedAttributes(), [1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setExcludedAttributes([1, 2])
        self.assertEqual(exporter.excludedAttributes(), [1, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula"
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setExcludedAttributes([0, 1, 2])
        self.assertEqual(exporter.excludedAttributes(), [0, 1, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test that excluded attributes take precedence over included

        exporter.setAttributes([1, 2])
        exporter.setExcludedAttributes([0, 1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setAttributes([])
        exporter.setExcludedAttributes([])

        # test excluding geometry
        exporter.setIncludeGeometry(False)
        self.assertEqual(exporter.includeGeometry(), False)
        feature.setGeometry(QgsGeometry(QgsLineString(l)))

        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setIncludeGeometry(True)

        feature.setGeometry(QgsGeometry(QgsPointV2(5, 6)))

        # test excluding attributes
        exporter.setIncludeAttributes(False)
        self.assertEqual(exporter.includeAttributes(), False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setIncludeGeometry(False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setIncludeAttributes(True)

        # test overriding ID
        expected = """{
   "type":"Feature",
   "id":29,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature, id=29), expected)

        # test injecting extra attributes
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198,
      "extra":"val1",
      "extra2":2
   }
}"""
        self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": 2}), expected)

        exporter.setIncludeAttributes(False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "extra":"val1",
      "extra2":{"nested_map":5,
"nested_map2":"val"},
      "extra3":[1,2,3]
   }
}"""
        self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": {"nested_map": 5, "nested_map2": "val"}, "extra3": [1, 2, 3]}), expected)
        exporter.setIncludeGeometry(True)
    def test_render_via_job(self):
        """
        Test rendering an annotation layer via a map render job
        """
        layer = QgsAnnotationLayer(
            'test',
            QgsAnnotationLayer.LayerOptions(
                QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())

        item = QgsAnnotationPolygonItem(
            QgsPolygon(
                QgsLineString([
                    QgsPoint(11.5, 13),
                    QgsPoint(12, 13),
                    QgsPoint(12, 13.5),
                    QgsPoint(11.5, 13)
                ])))
        item.setSymbol(
            QgsFillSymbol.createSimple({
                'color': '200,100,100',
                'outline_color': 'black',
                'outline_width': '2'
            }))
        item.setZIndex(1)
        i1_id = layer.addItem(item)

        item = QgsAnnotationLineItem(
            QgsLineString(
                [QgsPoint(11, 13),
                 QgsPoint(12, 13),
                 QgsPoint(12, 15)]))
        item.setSymbol(
            QgsLineSymbol.createSimple({
                'color': '#ffff00',
                'line_width': '3'
            }))
        item.setZIndex(2)
        i2_id = layer.addItem(item)

        item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
        item.setSymbol(
            QgsMarkerSymbol.createSimple({
                'color': '100,200,200',
                'size': '6',
                'outline_color': 'black'
            }))
        item.setZIndex(3)
        i3_id = layer.addItem(item)

        layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

        settings = QgsMapSettings()
        settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        settings.setExtent(QgsRectangle(10, 10, 18, 18))
        settings.setOutputSize(QSize(200, 200))
        settings.setLayers([layer])

        job = QgsMapRendererParallelJob(settings)
        job.start()
        job.waitForFinished()

        # check rendered item results
        item_results = job.takeRenderedItemResults()
        item_details = item_results.renderedItems()
        self.assertEqual(len(item_details), 3)
        self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3)
        self.assertCountEqual([i.itemId() for i in item_details],
                              [i1_id, i2_id, i3_id])
        self.assertCountEqual([
            i.itemId() for i in item_results.renderedAnnotationItemsInBounds(
                QgsRectangle(0, 0, 1, 1))
        ], [])
        self.assertCountEqual([
            i.itemId() for i in item_results.renderedAnnotationItemsInBounds(
                QgsRectangle(10, 10, 11, 18))
        ], [i2_id])
        self.assertCountEqual([
            i.itemId() for i in item_results.renderedAnnotationItemsInBounds(
                QgsRectangle(10, 10, 12, 18))
        ], [i1_id, i2_id, i3_id])

        # bounds should be in map crs
        self.assertEqual(
            [i.boundingBox() for i in item_details if i.itemId() == i1_id][0],
            QgsRectangle(11.5, 13, 12, 13.5))
        self.assertEqual(
            [i.boundingBox() for i in item_details if i.itemId() == i2_id][0],
            QgsRectangle(11, 13, 12, 15))
        self.assertEqual([
            i.boundingBox().toString(1) for i in item_details
            if i.itemId() == i3_id
        ][0], '11.5,12.5 : 12.5,13.5')