Пример #1
0
    def test_processRestriction(self):
        testLayerA = QgsVectorLayer(('{type}?crs=epsg:27700&index=yes'.format(
            type=QgsWkbTypes.displayString(QgsWkbTypes.LineString))), 'test1',
                                    'memory')
        self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.LineString)
        #print ('++++++ testLayerA type: {}'.format(QgsWkbTypes.displayString(testLayerA.wkbType())))

        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])

        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("RestrictionTypeID", QVariant.Int),
            QgsField("GeomShapeID", QVariant.Int),
            QgsField("AzimuthToRoadCentreLine", QVariant.Double)
        ])
        testFieldsA = testProviderA.fields()
        """for field in testFields:
            print ('** {}'.format(field.name()))"""

        testFeature1 = QgsFeature(testFieldsA)
        testFeature1.setGeometry(testLineString1)
        testFeature1.setAttributes(["Smith", 101, 1, 0])
        testProviderA.addFeatures([testFeature1])
        testLayerA.reload()

        self.testClass.processRestriction(testFeature1, testLayerA)
        print('*************************** Count: {}'.format(
            testLayerA.featureCount()))
        self.assertEqual(testLayerA.featureCount(), 2)
Пример #2
0
    def testSubsetStringFids(self):
        """
          - tests that feature ids are stable even if a subset string is set
          - tests that the subset string is correctly set on the ogr layer event when reloading the data source (issue #17122)
        """

        tmpfile = os.path.join(self.basetestpath, 'subsetStringFids.sqlite')
        ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid'])
        lyr.CreateField(ogr.FieldDefn('type', ogr.OFTInteger))
        lyr.CreateField(ogr.FieldDefn('value', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(0)
        f.SetField(0, 1)
        f.SetField(1, 11)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(1)
        f.SetField(0, 1)
        f.SetField(1, 12)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(2)
        f.SetField(0, 1)
        f.SetField(1, 13)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(3)
        f.SetField(0, 2)
        f.SetField(1, 14)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(4)
        f.SetField(0, 2)
        f.SetField(1, 15)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(5)
        f.SetField(0, 2)
        f.SetField(1, 16)
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.fields().at(0).name() == "orig_ogc_fid")

        req = QgsFeatureRequest()
        req.setFilterExpression("value=16")
        it = vl.getFeatures(req)
        f = QgsFeature()
        self.assertTrue(it.nextFeature(f))
        self.assertTrue(f.id() == 5)

        # Check that subset string is correctly set on reload
        vl.reload()
        self.assertTrue(vl.fields().at(0).name() == "orig_ogc_fid")
Пример #3
0
def points_along_line(layerout,
                      startpoint,
                      endpoint,
                      distance,
                      layer,
                      selected_only=True,
                      force_last=False,
                      force_first_last=False,
                      divide=0):
    """Adding Points along the line
    """

    crs = layer.crs().authid()

    layer_type = "memory"

    virt_layer = QgsVectorLayer("Point?crs=%s" % crs, layerout, layer_type)
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()  # actually writes attributes

    units = layer.crs().mapUnits()

    unitname = QgsUnitTypes.toString(units)
    provider.addAttributes([
        QgsField("fid", QVariant.Int),
        QgsField("cng" + unitname, QVariant.Double)
    ])

    def get_features():
        """Getting the features
        """
        if selected_only:
            return layer.selectedFeatures()
        else:
            return layer.getFeatures()

    # Loop through all (selected) features
    for feature in get_features():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsMessageLog.logMessage("No geometry", "QChainage")
            continue

        features = create_points(startpoint, endpoint, distance, geom, fid,
                                 force_last, force_first_last, divide)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    proj = QgsProject.instance()
    proj.addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()
    virt_layer.triggerRepaint()
    return
Пример #4
0
    def to_line_layer(self):
        source = "LineString?index=yes&crs={}".format(self.crs_id)
        layer = QgsVectorLayer(source, self.name, "memory")
        pr = layer.dataProvider()

        fields = QgsFields()

        # Section fields
        fields.append(QgsField("sec_id", QVariant.Int))
        fields.append(QgsField("sec_name", QVariant.String))
        fields.append(QgsField("abs_long", QVariant.Double))

        # Point fields
        fields.append(QgsField("p_id", QVariant.String))
        fields.append(QgsField("abs_lat", QVariant.String))
        fields.append(QgsField("zfond", QVariant.String))

        assert pr.addAttributes(fields)

        for section in self.sections.values():
            points = section.get_points()
            f = QgsFeature()
            f.setAttributes([
                section.id,
                section.name,
                section.pk,
                ",".join([str(i) for i in range(0, len(points))]),
                ",".join([str(p.d) for p in points]),
                ",".join([str(p.z) for p in points]),
            ])
            f.setGeometry(
                QgsGeometry(
                    QgsLineString([
                        QgsPoint(
                            point.x,
                            point.y,
                        ) if str(point.z) == "NULL" else QgsPoint(
                            point.x,
                            point.y,
                            point.z,
                        ) for point in points
                    ])))
            pr.addFeature(f)

        layer.reload()

        return layer
Пример #5
0
    def test_prepareNewLayer(self):

        testLayerA = QgsVectorLayer(('{type}?crs=epsg:27700&index=yes'.format(
            type=QgsWkbTypes.displayString(QgsWkbTypes.LineString))), 'test1',
                                    'memory')
        self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.LineString)
        #print ('++++++ testLayerA type: {}'.format(QgsWkbTypes.displayString(testLayerA.wkbType())))

        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])

        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("RestrictionTypeID", QVariant.Int),
            QgsField("GeomShapeID", QVariant.Int),
            QgsField("AzimuthToRoadCentreLine", QVariant.Double)
        ])
        testFieldsA = testProviderA.fields()
        """for field in testFields:
            print ('** {}'.format(field.name()))"""

        testFeature1 = QgsFeature(testFieldsA)
        testFeature1.setGeometry(testLineString1)
        testFeature1.setAttributes(["Smith", 101, 1, 0])
        testProviderA.addFeatures([testFeature1])
        testLayerA.reload()

        #print ('++++++ type: {}'.format(QgsWkbTypes.displayString(QgsWkbTypes.LineString)))
        self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.LineString)

        requiredFields = [
            QgsField("GeometryID", QVariant.String),
            QgsField("RestrictionTypeID", QVariant.Int)
        ]
        newLayerName = 'Test1_3'
        geomWbkType = QgsWkbTypes.MultiLineString

        newLayer = self.testClass.prepareNewLayer(testLayerA, newLayerName,
                                                  geomWbkType, requiredFields)
        self.assertIsNotNone(newLayer)
        self.assertEqual(newLayer.fields().count(), 2)
        #print ('++++++ new type: {}'.format(QgsWkbTypes.displayString(newLayer.wkbType())))
        self.assertEqual(newLayer.wkbType(), QgsWkbTypes.MultiLineString)
        print('==== newLayer crs:'.format(newLayer.crs().authid()))
Пример #6
0
def points_along_line(layerout, startpoint, endpoint, distance,
                      layer):  #,selected_only=True):#more from qchainage
    """Adding Points along the line"""
    # Create a new memory layer and add a distance attribute self.layerNameLine
    #layer_crs = virt_layer.setCrs(layer.crs())
    virt_layer = QgsVectorLayer("Point?crs=%s" % layer.crs().authid(),
                                layerout, "memory")
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()  # actually writes attributes
    units = layer.crs().mapUnits()

    unit_dic = {
        QgsUnitTypes.DistanceDegrees: 'Degrees',
        QgsUnitTypes.DistanceMeters: 'Meters',
        QgsUnitTypes.DistanceFeet: 'Feet',
        QgsUnitTypes.DistanceUnknownUnit: 'Unknown'
    }
    unit = unit_dic.get(units, 'Unknown')
    provider.addAttributes([QgsField("fid", qgis.PyQt.QtCore.QVariant.Int)])
    provider.addAttributes(
        [QgsField("cum_dist", qgis.PyQt.QtCore.QVariant.Int)])
    provider.addAttributes(
        [QgsField("unit", qgis.PyQt.QtCore.QVariant.String)])

    # Loop through all (selected) features
    for feature in layer.getSelectedFeatures():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsApplication.messageLog().logMessage("No geometry", "QChainage")
            continue

        features, xarray = create_points_at(startpoint, endpoint, distance,
                                            geom, fid, unit)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    QgsProject.instance().addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()
    virt_layer.triggerRepaint()
    return virt_layer, xarray
Пример #7
0
    def test_lazy(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "françéà", "ogr", QgsVectorLayer.LayerOptions(False))
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        df = QgsVirtualLayerDefinition()
        df.setQuery('select * from "françéà"')
        df.setLazy(True)

        vl = QgsVectorLayer(df.toString(), "testq", "virtual")
        self.assertEqual(vl.isValid(), True)
        ids = [f.id() for f in vl.getFeatures()]
        self.assertEqual(len(ids), 0)

        vl.reload()
        ids = [f.id() for f in vl.getFeatures()]
        self.assertEqual(len(ids), 4)

        QgsProject.instance().removeMapLayer(l1.id())
Пример #8
0
    def test_lazy(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "françéà", "ogr", QgsVectorLayer.LayerOptions(False))
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        df = QgsVirtualLayerDefinition()
        df.setQuery('select * from "françéà"')
        df.setLazy(True)

        vl = QgsVectorLayer(df.toString(), "testq", "virtual")
        self.assertEqual(vl.isValid(), True)
        ids = [f.id() for f in vl.getFeatures()]
        self.assertEqual(len(ids), 0)

        vl.reload()
        ids = [f.id() for f in vl.getFeatures()]
        self.assertEqual(len(ids), 4)

        QgsProject.instance().removeMapLayer(l1.id())
Пример #9
0
    def to_point_layer(self):
        source = "Point?index=yes&crs={}".format(self.crs_id)
        layer = QgsVectorLayer(source, self.name, "memory")
        pr = layer.dataProvider()

        fields = QgsFields()

        # Section fields
        fields.append(QgsField("sec_id", QVariant.Int))
        fields.append(QgsField("sec_name", QVariant.String))
        fields.append(QgsField("abs_long", QVariant.Double))

        # Point fields
        fields.append(QgsField("p_id", QVariant.Int))
        fields.append(QgsField("abs_lat", QVariant.Double))
        fields.append(QgsField("zfond", QVariant.Double))

        assert pr.addAttributes(fields)

        f = QgsFeature()
        for section in self.sections.values():
            for index, point in enumerate(section.get_points()):
                f.setAttributes([
                    section.id, section.name, section.pk, index, point.d,
                    point.z
                ])
                if str(point.z) == "NULL":
                    f.setGeometry(QgsGeometry(QgsPoint(
                        point.x,
                        point.y,
                    )))
                else:
                    f.setGeometry(
                        QgsGeometry(QgsPoint(
                            point.x,
                            point.y,
                            point.z,
                        )))
                pr.addFeature(f)

        layer.reload()

        return layer
    def taskFinished(self, data):
        self.dialog.runButton.setEnabled(True)
        self.dialog.cancel_button.setEnabled(False)

        self.sendDialogLog('process has been completed', self.greenColor)
        self.task.terminate()

        if self.dialog.addLayersWithError.isChecked():
            failPoints = data[0]
            failMultilines = data[1]

            if len(failPoints) != 0 or len(failMultilines) != 0:
                for l2rem in QgsProject.instance().mapLayersByName(
                        'AJBL_error_target_points'):
                    QgsProject.instance().removeMapLayer(l2rem)

                epsg = self.targetLayer.sourceCrs().authid()
                layer = QgsVectorLayer(f'Point?crs={epsg}',
                                       'AJBL_error_target_points', 'memory')
                QgsProject.instance().addMapLayer(layer, False)
                layerTree = self.iface.layerTreeCanvasBridge().rootGroup()
                layerTree.insertChildNode(0, QgsLayerTreeLayer(layer))
                layer.dataProvider().addAttributes(
                    [QgsField('Fail', QVariant.String)])

                for f in failPoints:
                    layer.startEditing()
                    feature = QgsFeature()
                    feature.setGeometry(f[0].geometry())
                    feature.setAttributes([f[1]])
                    layer.addFeature(feature)
                    layer.commitChanges()

                for f in failMultilines:
                    layer.startEditing()
                    feature = QgsFeature()
                    feature.setGeometry(f[0].geometry())
                    feature.setAttributes([f[1]])
                    layer.addFeature(feature)
                    layer.commitChanges()

                layer.reload()
Пример #11
0
    def testreloadData(self):
        ''' Test reloadData() '''

        tmpdir = tempfile.mkdtemp()
        self.dirs_to_cleanup.append(tmpdir)
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
        for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
            shutil.copy(os.path.join(srcpath, file), tmpdir)
        datasource = os.path.join(tmpdir, 'shapefile.shp')

        vl1 = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        vl2 = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl1.deleteAttributes([1]))
        self.assertTrue(vl1.commitChanges())
        self.assertEqual(len(vl1.fields()) + 1, len(vl2.fields()))
        # Reload
        vl2.reload()
        # And now check that fields are up-to-date
        self.assertEqual(len(vl1.fields()), len(vl2.fields()))
Пример #12
0
    def testreloadData(self):
        """ Test reloadData() """

        tmpdir = tempfile.mkdtemp()
        self.dirs_to_cleanup.append(tmpdir)
        srcpath = os.path.join(TEST_DATA_DIR, "provider")
        for file in glob.glob(os.path.join(srcpath, "shapefile.*")):
            shutil.copy(os.path.join(srcpath, file), tmpdir)
        datasource = os.path.join(tmpdir, "shapefile.shp")

        vl1 = QgsVectorLayer(u"{}|layerid=0".format(datasource), u"test", u"ogr")
        vl2 = QgsVectorLayer(u"{}|layerid=0".format(datasource), u"test", u"ogr")
        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl1.deleteAttributes([1]))
        self.assertTrue(vl1.commitChanges())
        self.assertEquals(len(vl1.fields()) + 1, len(vl2.fields()))
        # Reload
        vl2.reload()
        # And now check that fields are up-to-date
        self.assertEquals(len(vl1.fields()), len(vl2.fields()))
Пример #13
0
    def testreloadData(self):
        ''' Test reloadData() '''

        tmpdir = tempfile.mkdtemp()
        self.dirs_to_cleanup.append(tmpdir)
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
        for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
            shutil.copy(os.path.join(srcpath, file), tmpdir)
        datasource = os.path.join(tmpdir, 'shapefile.shp')

        vl1 = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        vl2 = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl1.deleteAttributes([1]))
        self.assertTrue(vl1.commitChanges())
        self.assertEqual(len(vl1.fields()) + 1, len(vl2.fields()))
        # Reload
        vl2.reload()
        # And now check that fields are up-to-date
        self.assertEqual(len(vl1.fields()), len(vl2.fields()))
Пример #14
0
    def testReloadDataAndFeatureCount(self):

        filename = '/vsimem/test.json'
        gdal.FileFromMemBuffer(filename, """{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": null, "geometry": { "type": "Point", "coordinates": [2, 49] } },
{ "type": "Feature", "properties": null, "geometry": { "type": "Point", "coordinates": [3, 50] } }
]
}""")
        vl = QgsVectorLayer(filename, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 2)
        gdal.FileFromMemBuffer(filename, """{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": null, "geometry": { "type": "Point", "coordinates": [2, 49] } }
]
}""")
        vl.reload()
        self.assertEqual(vl.featureCount(), 1)
        gdal.Unlink(filename)
Пример #15
0
    def addPointToLayer(self, x, y, z):
        x = float(x)
        y = float(y)
        z = float(z)

        name = 'Obliczone wysokości - GUGiK NMT'
        layers = QgsProject.instance().mapLayersByName(name)
        if not layers:
            layer = QgsVectorLayer(
                'PointZ?crs=epsg:2180&field=x:double&field=y:double&field=z:double',
                name, 'memory')
            QgsProject.instance().addMapLayer(layer, False)
            layerTree = self.iface.layerTreeCanvasBridge().rootGroup()
            layerTree.insertChildNode(0, QgsLayerTreeLayer(layer))

            treeRoot = QgsProject.instance().layerTreeRoot()
            if treeRoot.hasCustomLayerOrder():
                order = treeRoot.customLayerOrder()
                order.insert(
                    0,
                    order.pop(
                        order.index(
                            QgsProject.instance().mapLayersByName(name)[0])))
                treeRoot.setCustomLayerOrder(order)

            layer.loadNamedStyle(
                os.path.join(self.plugin_dir, 'layer_style.qml'), True)
        else:
            layer = layers[0]

        feature = QgsFeature()
        point = QgsGeometry(QgsPoint(x, y, z))
        feature.setGeometry(point)
        feature.setAttributes([x, y, z])
        layer.startEditing()
        layer.addFeature(feature)
        layer.commitChanges()
        layer.reload()
Пример #16
0
    def test_processLayer(self):
        testLayerA = QgsVectorLayer(('{type}?crs=epsg:27700&index=yes'.format(
            type=QgsWkbTypes.displayString(QgsWkbTypes.MultiLineString))),
                                    'testA', 'memory')
        self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.MultiLineString)
        # print ('++++++ testLayerA type: {}'.format(QgsWkbTypes.displayString(testLayerA.wkbType())))

        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])

        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("RestrictionTypeID", QVariant.Int),
            QgsField("GeomShapeID", QVariant.Int),
            QgsField("AzimuthToRoadCentreLine", QVariant.Double)
        ])
        testFieldsA = testProviderA.fields()
        """for field in testFields:
            print ('** {}'.format(field.name()))"""

        testFeature1 = QgsFeature(testFieldsA)
        testFeature1.setGeometry(testLineString1)
        testFeature1.setAttributes(["Smith", 101, 1, 0])
        testProviderA.addFeatures([testFeature1])
        testLayerA.reload()

        requiredFields = ["GeometryID", "RestrictionTypeID"]
        outputLayersList = self.testClass.processLayer(testLayerA,
                                                       requiredFields)
        self.assertEqual(len(outputLayersList), 1)
        self.assertEqual(len(outputLayersList[0][1].fields()), 2)

        # TODO: Need to include tests for relations - finding lookup fields and returning values ...
        """ Cases are:
Пример #17
0
    def test_setFieldsForTOMsExportLayer(self):

        TOMsRequiredFields = [
            "GeometryID",
            "RestrictionTypeID",
            "RestType",
            "NrBays",
            "TimePeriodID",
            "PayTypeID",
            "MaxStayID",
            "NoReturnID",
            "BaysWordingID",
            "RoadName",
            "USRN",
            "OpenDate",
            "CPZ",
            "ParkingTariffArea",
            "Restriction_Length",  # for bays
            "NoWaitingTimeID",
            "NoLoadingTimeID",  # for lines
            "AreaPermitCode"  # for polygons
        ]
        testLayerA = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'),
                                    'test1', 'memory')
        testProviderA = testLayerA.dataProvider()
        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("RestrictionTypeID", QVariant.Int),
            QgsField("NrBays", QVariant.Int),
            QgsField("size2", QVariant.Double)
        ])
        testLayerA.reload()

        reqFields = self.testClass.setFieldsForTOMsExportLayer(
            testLayerA, TOMsRequiredFields)
        self.assertEqual(len(reqFields), 3)
Пример #18
0
    def test_saveLayerToGpkg(self):
        testLayerA = QgsVectorLayer(('{type}?crs=epsg:27700&index=yes'.format(
            type=QgsWkbTypes.displayString(QgsWkbTypes.MultiLineString))),
                                    'testA', 'memory')
        self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.MultiLineString)
        #print ('++++++ testLayerA type: {}'.format(QgsWkbTypes.displayString(testLayerA.wkbType())))

        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])

        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("RestrictionTypeID", QVariant.Int),
            QgsField("GeomShapeID", QVariant.Int),
            QgsField("AzimuthToRoadCentreLine", QVariant.Double)
        ])
        testFieldsA = testProviderA.fields()
        """for field in testFields:
            print ('** {}'.format(field.name()))"""

        testFeature1 = QgsFeature(testFieldsA)
        testFeature1.setGeometry(testLineString1)
        testFeature1.setAttributes(["Smith", 101, 1, 0])
        testProviderA.addFeatures([testFeature1])
        testLayerA.reload()

        fileName = 'C:\\Users\\marie_000\\Documents\\MHTC\\tmp\\test1.gpkg'
        self.testClass.saveLayerToGpkg(testLayerA, fileName)

        ds = ogr.Open(fileName)
        lyr = ds.GetLayerByName('testA')
        self.assertIsNotNone(lyr)
        f = lyr.GetNextFeature()
        self.assertEqual(f['GeometryID'], 'Smith')
Пример #19
0
def points_along_line(layerout,
                      startpoint,
                      endpoint,
                      distance,
                      label,
                      layer,
                      selected_only=True,
                      force=False,
                      divide=0):
    """Adding Points along the line
    """
    # Create a new memory layer and add a distance attribute self.layerNameLine
    #layer_crs = virt_layer.setCrs(layer.crs())
    virt_layer = QgsVectorLayer("Point?crs=%s" % layer.crs().authid(),
                                layerout,
                                "memory")
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()   # actually writes attributes
    units = layer.crs().mapUnits()
    unit_dic = {
        QGis.Degrees: 'Degrees',
        QGis.Meters: 'Meters',
        QGis.Feet: 'Feet',
        QGis.UnknownUnit: 'Unknown'}
    unit = unit_dic.get(units, 'Unknown')
    provider.addAttributes([QgsField("fid", QVariant.Int)])
    provider.addAttributes([QgsField("cng_("+unit+")", QVariant.Int)])

    def get_features():
        """Getting the features
        """
        if selected_only:
            return layer.selectedFeatures()
        else:
            return layer.getFeatures()

    # Loop through all (selected) features
    for feature in get_features():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsMessageLog.logMessage("No geometry", "QChainage")
            continue

        features = create_points_at(startpoint, endpoint, distance, geom,
                                    fid, force, divide)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()

    #from here Add labeling
    #generic labeling properties
    if label:
        virt_layer.setCustomProperty("labeling", "pal")
        virt_layer.setCustomProperty("labeling/enabled", "true")
        virt_layer.setCustomProperty("labeling/fieldName", "cng_("+unit+")")
        virt_layer.setCustomProperty("labeling/fontSize", "10")
        virt_layer.setCustomProperty("labeling/multiLineLabels", "true")

        #virt_layer.setCustomProperty("labeling/Size", "5")
    # symbol = QgsMarkerSymbolV2.createSimple({"name": "capital"})
    # virt_layer.setRendererV2(QgsSingleSymbolRendererV2(symbol))
    virt_layer.triggerRepaint()
    return
Пример #20
0
    def testSubsetStringFids(self):
        """
          - tests that feature ids are stable even if a subset string is set
          - tests that the subset string is correctly set on the ogr layer event when reloading the data source (issue #17122)
        """

        tmpfile = os.path.join(self.basetestpath, 'subsetStringFids.sqlite')
        ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid'])
        lyr.CreateField(ogr.FieldDefn('type', ogr.OFTInteger))
        lyr.CreateField(ogr.FieldDefn('value', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(0)
        f.SetField(0, 1)
        f.SetField(1, 11)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(1)
        f.SetField(0, 1)
        f.SetField(1, 12)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(2)
        f.SetField(0, 1)
        f.SetField(1, 13)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(3)
        f.SetField(0, 2)
        f.SetField(1, 14)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(4)
        f.SetField(0, 2)
        f.SetField(1, 15)
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(5)
        f.SetField(0, 2)
        f.SetField(1, 16)
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid")

        req = QgsFeatureRequest()
        req.setFilterExpression("value=16")
        it = vl.getFeatures(req)
        f = QgsFeature()
        self.assertTrue(it.nextFeature(f))
        self.assertTrue(f.id() == 5)

        # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed
        req = QgsFeatureRequest()
        req.setSubsetOfAttributes([])
        it = vl.getFeatures(req)
        ids = []
        while it.nextFeature(f):
            ids.append(f.id())
        self.assertTrue(len(ids) == 3)
        self.assertTrue(3 in ids)
        self.assertTrue(4 in ids)
        self.assertTrue(5 in ids)

        # Check that subset string is correctly set on reload
        vl.reload()
        self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid")
Пример #21
0
def points_along_line(layerout,
                      startpoint,
                      endpoint,
                      distance,
                      label,
                      layer,
                      selected_only=True,
                      force=False,
                      fo_fila=False,
                      divide=0,
                      decimal=2):
    """Adding Points along the line
    """

    crs = layer.crs().authid()
    # TODO check for virtual or shapelayer and set virt_layer according to it
    shape = False
    if shape:
        # define fields for feature attributes. A list of QgsField objects is needed
        fields = [QgsField("first", QVariant.Int),
                  QgsField("second", QVariant.String)]
        # create an instance of vector file writer, which will create the vector file.
        # Arguments:
        # 1. path to new file (will fail if exists already)
        # 2. encoding of the attributes
        # 3. field map
        # 4. geometry type - from WKBTYPE enum
        # 5. layer's spatial reference (instance of
        #    QgsCoordinateReferenceSystem) - optional
        # 6. driver name for the output file
        writer = QgsVectorFileWriter("my_shapes.shp",
                                     "CP1250",
                                     fields,
                                     QGis.WKBPoint,
                                     crs,
                                     "ESRI Shapefile")
        if writer.hasError() != QgsVectorFileWriter.NoError:
            print "Error when creating shapefile: ", writer.hasError()
        # add a feature
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10)))
        fet.setAttributes([1, "text"])
        writer.addFeature(fet)
        # delete the writer to flush features to disk (optional)
        del writer

        layer_type = "Shapefile"  # TODO Add Shapefile functionality here
    else:
        layer_type = "memory"

    virt_layer = QgsVectorLayer("Point?crs=%s" % crs,
                                layerout,
                                layer_type)
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()   # actually writes attributes
    units = layer.crs().mapUnits()
    unit_dic = {
        QGis.Degrees: 'Degrees',
        QGis.Meters: 'Meters',
        QGis.Feet: 'Feet',
        QGis.UnknownUnit: 'Unknown'}
    unit = unit_dic.get(units, 'Unknown')
    provider.addAttributes([QgsField("fid", QVariant.Int),
                            QgsField("cng_("+unit+")", QVariant.Double)])

    def get_features():
        """Getting the features
        """
        if selected_only:
            return layer.selectedFeatures()
        else:
            return layer.getFeatures()

    # Loop through all (selected) features
    for feature in get_features():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsMessageLog.logMessage("No geometry", "QChainage")
            continue

        features = create_points_at(startpoint,
                                    endpoint,
                                    distance,
                                    geom,
                                    fid,
                                    force,
                                    fo_fila,
                                    divide)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()

    # from here Add labeling
    # generic labeling properties
    if label:
        virt_layer.setCustomProperty("labeling", "pal")
        virt_layer.setCustomProperty("labeling/enabled", "true")
        virt_layer.setCustomProperty("labeling/fieldName", "cng_("+unit+")")
        virt_layer.setCustomProperty("labeling/fontSize", "10")
        virt_layer.setCustomProperty("labeling/multiLineLabels", "true")
        virt_layer.setCustomProperty("labeling/formatNumbers", "true")
        virt_layer.setCustomProperty("labeling/decimals", decimal)

        # virt_layer.setCustomProperty("labeling/Size", "5")
    # symbol = QgsMarkerSymbolV2.createSimple({"name": "capital"})
    # virt_layer.setRendererV2(QgsSingleSymbolRendererV2(symbol))
    virt_layer.triggerRepaint()
    return
Пример #22
0
class ImportPhotos:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'ImportPhotos_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&ImportPhotos')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'ImportPhotos')
        self.toolbar.setObjectName(u'ImportPhotos')

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('ImportPhotos', message)

    def add_action(
            self,
            icon_path,
            text,
            callback,
            enabled_flag=True,
            add_to_menu=True,
            add_to_toolbar=True,
            status_tip=None,
            whats_this=None,
            parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        # Create the dialog (after translation) and keep reference

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        icon_path = ':/plugins/ImportPhotos/svg/ImportImage.svg'
        self.add_action(
            icon_path,
            text=self.tr(u'Import Photos'),
            callback=self.run,
            parent=self.iface.mainWindow())
        icon_path = ':/plugins/ImportPhotos/svg/SelectImage.svg'
        self.clickPhotos = self.add_action(
            icon_path,
            text=self.tr(u'Click Photos'),
            callback=self.mouseClick,
            parent=self.iface.mainWindow())
        self.dlg = ImportPhotosDialog()
        self.dlg.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint)

        self.dlg.ok.clicked.connect(self.ok)
        self.dlg.closebutton.clicked.connect(self.close)
        self.dlg.toolButtonImport.clicked.connect(self.toolButtonImport)
        self.dlg.toolButtonOut.clicked.connect(self.toolButtonOut)

        self.clickPhotos.setCheckable(True)
        self.clickPhotos.setEnabled(True)

        self.listPhotos = []
        self.layernamePhotos = []
        self.canvas = self.iface.mapCanvas()
        self.toolMouseClick = MouseClick(self.canvas, self)

        self.fields = ['ID', 'Name', 'Date', 'Time', 'Lon', 'Lat', 'Altitude', 'North', 'Azimuth', 'Camera Maker',
                       'Camera Model', 'Path']

        self.extension_switch = {
            ".shp": "ESRI Shapefile",
            ".geojson": "GeoJSON",
            ".gpkg":"GPKG",
            ".csv": "CSV",
            ".kml": "KML",
            ".tab": "MapInfo File",
            ".ods": "ODS"
        }

    def mouseClick(self):
        try:
            self.iface.setActiveLayer(self.canvas.layers()[0])
        except:
            pass
        self.canvas.setMapTool(self.toolMouseClick)
        self.clickPhotos.setChecked(True)

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&ImportPhotos'),
                action)
            self.iface.removeToolBarIcon(action)
            # remove the toolbar
        del self.toolbar

    def run(self):
        self.dlg.ok.setEnabled(True)
        self.dlg.closebutton.setEnabled(True)
        self.dlg.toolButtonImport.setEnabled(True)
        self.dlg.toolButtonOut.setEnabled(True)
        self.clickPhotos.setEnabled(True)
        self.dlg.out.setText('')
        self.dlg.imp.setText('')
        self.dlg.show()

    def close(self):
        self.dlg.close()

    def toolButtonOut(self):
        typefiles = 'ESRI Shapefile (*.shp *.SHP);; GeoJSON (*.geojson *.GEOJSON);; GeoPackage (*.gpkg *.GPKG);; Comma Separated Value (*.csv *.CSV);; Keyhole Markup Language (*.kml *.KML);; Mapinfo TAB (*.tab *.TAB);; Open Document Spreadsheet (*.ods *.ODS)'
        if platform.system() == 'Linux':
            try:
                self.outputPath, self.extension = QFileDialog.getSaveFileNameAndFilter(None, 'Save File', os.path.join(
                    os.path.join(os.path.expanduser('~')),
                    'Desktop'), typefiles)
            except:
                self.outputPath = QFileDialog.getSaveFileName(None, 'Save File', os.path.join(
                    os.path.join(os.path.expanduser('~')),
                    'Desktop'), typefiles) #hack line
        else:
            self.outputPath = QFileDialog.getSaveFileName(None, 'Save File', os.path.join(
                os.path.join(os.path.expanduser('~')),
                'Desktop'), typefiles)

        self.outputPath = self.outputPath[0]
        self.dlg.out.setText(self.outputPath)

    def toolButtonImport(self):
        self.directoryPhotos = QFileDialog.getExistingDirectory(None, 'Select a folder:',
                                                                os.path.join(os.path.join(os.path.expanduser('~')),
                                                                             'Desktop'), QFileDialog.ShowDirsOnly)
        self.dlg.imp.setText(self.directoryPhotos)

    def selectDir(self):
        title = 'Warning'
        msg = 'Please select a directory photos.'
        self.showMessage(title, msg, 'Warning')
        return True

    def selectOutp(self):
        title = 'Warning'
        msg = 'Please define output file location.'
        self.showMessage(title, msg, 'Warning')
        return True

    def noImageFound(self):
        title = 'Warning'
        msg = 'No image path found.'
        self.showMessage(title, msg, 'Warning')
        return True

    def ok(self):
        if self.dlg.imp.text() == '':
            if self.selectDir():
                return
        if not os.path.isdir(self.dlg.imp.text()):
            if self.selectDir():
                return
        if self.dlg.out.text() == '':
            if self.selectOutp():
                return
        if not os.path.isabs(self.dlg.out.text()):
            if self.selectOutp():
                return

        if platform.system() == 'Linux':
            self.lphoto = os.path.basename(self.outputPath)
            try:
                self.extension = '.'+self.extension.split()[-1][2:-1].lower()
            except:
                self.extension = '.shp' #hack line, temporary
        else:
            _ , self.extension = os.path.splitext(self.outputPath)
            basename = os.path.basename(self.outputPath)
            self.lphoto = basename[:-len(self.extension)]

        self.outputPath = self.dlg.out.text()
        self.directoryPhotos = self.dlg.imp.text()
        self.outDirectoryPhotosGeoJSON = self.plugin_dir + '/tmp.geojson'

        self.dlg.ok.setEnabled(False)
        self.dlg.closebutton.setEnabled(False)
        self.dlg.toolButtonImport.setEnabled(False)
        self.dlg.toolButtonOut.setEnabled(False)

        # get paths of photos
        extens = ['jpg', 'jpeg', 'JPG', 'JPEG']
        self.photos = []
        for root, dirs, files in os.walk(self.directoryPhotos):
            self.photos.extend(os.path.join(root, name) for name in files
                          if name.lower().endswith(tuple(extens)))

        self.initphotos = len(self.photos)

        if self.initphotos == 0:
            title = 'Warning'
            msg = 'No photos.'
            self.showMessage(title, msg, 'Warning')
            self.dlg.ok.setEnabled(True)
            self.dlg.closebutton.setEnabled(True)
            self.dlg.toolButtonImport.setEnabled(True)
            self.dlg.toolButtonOut.setEnabled(True)
            self.clickPhotos.setChecked(True)
            return

        self.canvas.setMapTool(self.toolMouseClick)

        self.truePhotosCount = 0

        self.Qpr_inst = QgsProject.instance()
        if platform.system()=='Darwin':
            self.layernamePhotos.append(self.lphoto+' OGRGeoJSON Point')
        else:
            self.layernamePhotos.append(self.lphoto)

        if platform.system() == 'Linux':
            self.outputPath = self.outputPath + self.extension
            self.extension = self.extension_switch[self.extension]
        else:
            self.extension = self.extension_switch[self.extension.lower()]

        self.exifread_module = False
        self.pil_module = False

        if CHECK_MODULE == '':
            self.showMessage('Python Modules', 'Please install python module "exifread" or "PIL".' , 'Warning')

        #self.import_photos_task('', '')
        self.call_import_photos()
        self.dlg.close()

    def refresh(self):  # Deselect features
        mc = self.canvas
        for layer in mc.layers():
            if layer.type() == layer.VectorLayer:
                layer.removeSelection()
        mc.refresh()

    def showMessage(self, title, msg, icon):
        if icon == 'Warning':
            icon = QMessageBox.Warning
        elif icon == 'Information':
            icon = QMessageBox.Information

        msgBox = QMessageBox()
        msgBox.setIcon(icon)
        msgBox.setWindowTitle(title)
        msgBox.setText(msg)
        msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint)
        msgBox.exec_()

    def completed(self, exception, result=None):
        geojson = {"type": "FeatureCollection",
                   "name": self.lphoto,
                   "crs": {"type": "name", "properties": {"name": "crs:OGC:1.3:CRS84"}},
                   "features": self.geoPhotos}

        geofile = open(self.plugin_dir + '/tmp.geojson', 'w')
        json.dump(geojson, geofile)
        geofile.close()
        del self.geoPhotos, geojson

        try:
            for layer in self.canvas.layers():
                if layer.publicSource() == self.outputPath:
                    self.Qpr_inst.instance().removeMapLayer(layer.id())
                    os.remove(self.outputPath)
        except:
            pass

        self.layerPhotos = QgsVectorLayer(self.outDirectoryPhotosGeoJSON, self.lphoto, "ogr")
        QgsVectorFileWriter.writeAsVectorFormat(self.layerPhotos, self.outputPath, "utf-8",
                                                    QgsCoordinateReferenceSystem(self.layerPhotos.crs().authid()),
                                                    self.extension)
        self.layerPhotos_final = QgsVectorLayer(self.outputPath, self.lphoto, "ogr")

        # clear temp.geojson file
        try:
            f = open(self.outDirectoryPhotosGeoJSON, 'r+')
            f.truncate(0)  # need '0' when using r+
        except:
            pass

        try:
            self.layerPhotos_final.loadNamedStyle(self.plugin_dir + "/svg/photos.qml")
        except:
            title = 'Warning'
            msg = 'No geo-tagged images were detected.'
            self.showMessage(title, msg, 'Warning')
            self.taskPhotos.destroyed()
            return

        self.layerPhotos_final.setReadOnly(False)
        self.layerPhotos_final.reload()
        self.layerPhotos_final.triggerRepaint()

        try:
            xmin = min(self.lon)
            ymin = min(self.lat)
            xmax = max(self.lon)
            ymax = max(self.lat)
            self.canvas.zoomToSelected(self.layerPhotos_final)
            self.canvas.setExtent(QgsRectangle(xmin, ymin, xmax, ymax))
        except:
            pass

        ###########################################
        self.dlg.ok.setEnabled(True)
        self.dlg.closebutton.setEnabled(True)
        self.dlg.toolButtonImport.setEnabled(True)
        self.dlg.toolButtonOut.setEnabled(True)
        self.clickPhotos.setChecked(True)

        noLocationPhotosCounter = self.initphotos - self.truePhotosCount
        if self.truePhotosCount == noLocationPhotosCounter == 0 or self.truePhotosCount == 0:
            title = 'Import Photos'
            msg = 'Import Completed.\n\nDetails:\n  No new photos were added.'
            self.showMessage(title, msg, 'Information')
            self.taskPhotos.destroyed()
            return
        elif (self.truePhotosCount == self.initphotos) or ((noLocationPhotosCounter + self.truePhotosCount) == self.initphotos):
            title = 'Import Photos'
            msg = 'Import Completed.\n\nDetails:\n  ' + str(
                int(self.truePhotosCount)) + ' photo(s) added without error.\n  ' + str(
                int(noLocationPhotosCounter)) + ' photo(s) skipped (because of missing location).'
            self.showMessage(title, msg, 'Information')

        self.Qpr_inst.addMapLayers([self.layerPhotos_final])
        
        self.taskPhotos.destroyed()

    def stopped(self, task):
        QgsMessageLog.logMessage(
            'Task "{name}" was canceled'.format(
                name=task.description()),
            'ImportPhotos', Qgis.Info)

    def import_photos_task(self, task, wait_time):
        self.geoPhotos = []
        self.lon = []
        self.lat = []
        for count, imgpath in enumerate(self.photos):
            try:
                name = os.path.basename(imgpath)
                if CHECK_MODULE == 'exifread' and not self.pil_module:
                    self.exifread_module = True
                    self.taskPhotos.setProgress(count/self.initphotos)
                    with open(imgpath, 'rb') as imgpathF:
                        tags = exifread.process_file(imgpathF, details=False)
                    if not tags.keys() & {"GPS GPSLongitude", "GPS GPSLatitude"}:
                        continue

                    lat, lon = self.get_exif_location(tags, "lonlat")
                    try:
                        altitude = float(tags["GPS GPSAltitude"].values[0].num) / float(
                            tags["GPS GPSAltitude"].values[0].den)
                    except:
                        altitude = ''
                    uuid_ = str(uuid.uuid4())
                    try:
                        dt1, dt2 = tags["EXIF DateTimeOriginal"].values.split()
                        date = dt1.replace(':', '/')
                        time_ = dt2
                        timestamp = dt1.replace(':', '-') + 'T' + time_
                    except:
                        try:
                            date = tags["GPS GPSDate"].values.replace(':', '/')
                            tt = [str(i) for i in tags["GPS GPSTimeStamp"].values]
                            time_ = "{:0>2}:{:0>2}:{:0>2}".format(tt[0], tt[1], tt[2])
                            timestamp = tags["GPS GPSDate"].values.replace(':', '-') + 'T' + time_
                        except:
                            date = ''
                            time_ = ''
                            timestamp = ''
                    try:
                        azimuth = float(tags["GPS GPSImgDirection"].values[0].num) / float(
                            tags["GPS GPSImgDirection"].values[0].den)
                    except:
                        azimuth = ''
                    try:
                        north = str(tags["GPS GPSImgDirectionRef"].values)
                    except:
                        north = ''
                    try:
                        maker = tags['Image Make']
                    except:
                        maker = ''
                    try:
                        model = tags['Image Model']
                    except:
                        model = ''

                if CHECK_MODULE == 'PIL' and not self.exifread_module:
                    self.pil_module = True
                    a = {}
                    info = Image.open(imgpath)
                    info = info._getexif()

                    if info == None:
                        continue

                    for tag, value in info.items():
                        if TAGS.get(tag, tag) == 'GPSInfo' or TAGS.get(tag, tag) == 'DateTime' or TAGS.get(tag,
                                                                                                           tag) == 'DateTimeOriginal':
                            a[TAGS.get(tag, tag)] = value

                    if a == {}:
                        continue

                    if a['GPSInfo'] != {}:
                        if 1 and 2 and 3 and 4 in a['GPSInfo']:
                            lat = [float(x) / float(y) for x, y in a['GPSInfo'][2]]
                            latref = a['GPSInfo'][1]
                            lon = [float(x) / float(y) for x, y in a['GPSInfo'][4]]
                            lonref = a['GPSInfo'][3]

                            lat = lat[0] + lat[1] / 60 + lat[2] / 3600
                            lon = lon[0] + lon[1] / 60 + lon[2] / 3600

                            if latref == 'S':
                                lat = -lat
                            if lonref == 'W':
                                lon = -lon
                        else:
                            continue

                        uuid_ = str(uuid.uuid4())
                        if 'DateTime' or 'DateTimeOriginal' in a:
                            if 'DateTime' in a:
                                dt1, dt2 = a['DateTime'].split()
                            if 'DateTimeOriginal' in a:
                                dt1, dt2 = a['DateTimeOriginal'].split()
                            date = dt1.replace(':', '/')
                            time_ = dt2
                            timestamp = dt1.replace(':', '-') + 'T' + time_

                        if 6 in a['GPSInfo']:
                            if len(a['GPSInfo'][6]) > 1:
                                mAltitude = float(a['GPSInfo'][6][0])
                                mAltitudeDec = float(a['GPSInfo'][6][1])
                                altitude = mAltitude / mAltitudeDec
                        else:
                            altitude = ''

                        if 16 and 17 in a['GPSInfo']:
                            north = str(a['GPSInfo'][16])
                            azimuth = float(a['GPSInfo'][17][0]) / float(a['GPSInfo'][17][1])
                        else:
                            north = ''
                            azimuth = ''

                        maker = ''
                        model = ''
                self.lon.append(lon)
                self.lat.append(lat)
                self.truePhotosCount = self.truePhotosCount + 1

                geo_info = {"type": "Feature",
                            "properties": {'ID': uuid_, 'Name': name, 'Date': date, 'Time': time_,
                                           'Lon': lon,
                                           'Lat': lat, 'Altitude': altitude, 'North': north,
                                           'Azimuth': azimuth,
                                           'Camera Maker': str(maker), 'Camera Model': str(model), 'Path': imgpath,
                                           'Timestamp': timestamp},
                            "geometry": {"coordinates": [lon, lat], "type": "Point"}}
                self.geoPhotos.append(geo_info)

                if self.taskPhotos.isCanceled():
                    self.stopped(self.taskPhotos)
                    self.taskPhotos.destroyed()
                    return None
            except:
                pass
        return True

    def call_import_photos(self):
        self.taskPhotos = QgsTask.fromFunction(u'ImportPhotos', self.import_photos_task,
                                 on_finished=self.completed, wait_time=4)
        QgsApplication.taskManager().addTask(self.taskPhotos)

######################################################
# based on http://www.codegists.com/snippet/python/exif_gpspy_snakeye_python

    def _get_if_exist(self, data, key):
        if key in data:
            return data[key]

        return None


    def _convert_to_degress(self, value):
        """
        Helper function to convert the GPS coordinates stored in the EXIF to degress in float format

        :param value:
        :type value: exifread.utils.Ratio
        :rtype: float
        """
        d = float(value.values[0].num) / float(value.values[0].den)
        m = float(value.values[1].num) / float(value.values[1].den)
        s = float(value.values[2].num) / float(value.values[2].den)

        return d + (m / 60.0) + (s / 3600.0)


    def get_exif_location(self, exif_data, lonlat):
        """
        Returns the latitude and longitude, if available, from the provided exif_data (obtained through get_exif_data above)
        """

        if lonlat=='lonlat':
            lat = ''
            lon = ''
            gps_latitude = self._get_if_exist(exif_data, 'GPS GPSLatitude')
            gps_latitude_ref = self._get_if_exist(exif_data, 'GPS GPSLatitudeRef')
            gps_longitude = self._get_if_exist(exif_data, 'GPS GPSLongitude')
            gps_longitude_ref = self._get_if_exist(exif_data, 'GPS GPSLongitudeRef')

            if gps_latitude and gps_latitude_ref and gps_longitude and gps_longitude_ref:
                lat = self._convert_to_degress(gps_latitude)
                if gps_latitude_ref.values[0] != 'N':
                    lat = 0 - lat

                lon = self._convert_to_degress(gps_longitude)
                if gps_longitude_ref.values[0] != 'E':
                    lon = 0 - lon

            return lat, lon
Пример #23
0
    def get_inner_rings_layer(self,
                              plot_layer,
                              id_field=ID_FIELD,
                              use_selection=False):
        id_field_idx = plot_layer.fields().indexFromName(id_field)
        request = QgsFeatureRequest().setSubsetOfAttributes([id_field_idx])
        polygons = plot_layer.getSelectedFeatures(
            request) if use_selection else plot_layer.getFeatures(request)

        layer = QgsVectorLayer("LineString?crs=EPSG:{}".format(DEFAULT_EPSG),
                               "rings", "memory")
        data_provider = layer.dataProvider()
        data_provider.addAttributes([QgsField(ID_FIELD, QVariant.Int)])
        layer.updateFields()

        features = []

        for polygon in polygons:
            polygon_geom = polygon.geometry()
            is_multipart = polygon_geom.isMultipart()

            # Does the current multipolygon have inner rings?
            has_inner_rings = False
            multi_polygon = None
            single_polygon = None

            if is_multipart:

                multi_polygon = polygon_geom.constGet()

                # TODO: remove when the error is resolved
                if type(multi_polygon) != QgsMultiPolygon:
                    geom = QgsMultiPolygon()
                    geom.fromWkt(polygon_geom.asWkt())
                    multi_polygon = geom

                for part in range(multi_polygon.numGeometries()):
                    if multi_polygon.ringCount(part) > 1:
                        has_inner_rings = True
                        break
            else:
                single_polygon = polygon_geom.constGet()

                # TODO: remove when the error is resolved
                if type(single_polygon) != QgsPolygon:
                    geom = QgsPolygon()
                    geom.fromWkt(polygon_geom.asWkt())
                    single_polygon = geom

                if single_polygon.numInteriorRings() > 0:
                    has_inner_rings = True

            if has_inner_rings:

                if is_multipart and multi_polygon:
                    for i in range(multi_polygon.numGeometries()):
                        temp_polygon = multi_polygon.geometryN(i)

                        # TODO: remove when the error is resolved
                        if type(temp_polygon) != QgsPolygon:
                            geom = QgsPolygon()
                            geom.fromWkt(temp_polygon.asWkt())
                            temp_polygon = geom

                        for j in range(temp_polygon.numInteriorRings()):
                            new_feature = QgsVectorLayerUtils().createFeature(
                                layer,
                                QgsGeometry(
                                    temp_polygon.interiorRing(j).clone()),
                                {0: polygon[id_field]})
                            features.append(new_feature)

                elif not is_multipart and single_polygon:
                    for j in range(single_polygon.numInteriorRings()):
                        new_feature = QgsVectorLayerUtils().createFeature(
                            layer,
                            QgsGeometry(
                                single_polygon.interiorRing(j).clone()),
                            {0: polygon[id_field]})
                        features.append(new_feature)

        layer.dataProvider().addFeatures(features)
        layer.updateExtents()
        layer.reload()
        return layer
Пример #24
0
class ImageViewer:
    timer = None
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'ImageViewer_{}.qm'.format(locale))

        threadcount = QThread.idealThreadCount()
        # use all available cores and parallel rendering
        QgsApplication.setMaxThreads(threadcount)
        QSettings().setValue("/qgis/parallel_rendering", True)
        # OpenCL acceleration
        QSettings().setValue("/core/OpenClEnabled", True)
        self.canvas = self.iface.mapCanvas()
        self.dlg1 = None

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&Image Viewer')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads

    def createTimer(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.onTimer)
        self.timer.start(10)

    def onTimer(self):
        try:
            cefpython.MessageLoopWork()
        except Exception:
            None

    def stopTimer(self):
        self.timer.stop()

    def StartCefPython(self):
        ''' Start CefPython '''
        settings = {}
        settings["browser_subprocess_path"] = "%s/%s" % (
            cefpython.GetModuleDirectory(), "subprocess")
        settings["log_severity"] = cefpython.LOGSEVERITY_DISABLE
        settings["context_menu"] = {
            "enabled": False,
            "navigation": False,  # Back, Forward, Reload
            "print": False,
            "view_source": False,
            "external_browser": False,  # Open in external browser
            "devtools": False,  # Developer Tools
        }
        sys.argv = ['']
        cefpython.Initialize(settings)
       # cefpython.Initialize(settings={"file_access_from_file_urls_allowed": True})

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('ImageViewer', message)


    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """
        # Create the dialog (after translation) and keep reference

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        log.initLogging()
        icon_path = ':/plugins/image_viewer/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'ImageViewer'),
            callback=self.run,
            parent=self.iface.mainWindow())
        icon_path = ':/plugins/image_viewer/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'360viewer'),
            callback=self.mouseClick,
            parent=self.iface.mainWindow())

        self.dlg = ImageViewerDialog()
        self.dlg.ok.clicked.connect(self.ok)
        self.dlg.closebutton.clicked.connect(self.close)
        self.dlg.toolButtonImport.clicked.connect(self.toolButtonImport)
        self.dlg.toolButtonOut.clicked.connect(self.toolButtonOut)

        self.listPhotos = []
        self.layernamePhotos = []
        self.canvas = self.iface.mapCanvas()

        self.fields = ['Order', 'Name', 'Date', 'Time', 'Lon', 'Lat', 'Altitude', 'North', 'Azimuth', 'Camera Maker',
                       'Camera Model', 'Title', 'Comment', 'Path', 'RelPath', 'Timestamp']

        self.extension_switch = {
            ".shp": "ESRI Shapefile",
            ".geojson": "GeoJSON",
            ".gpkg": "GPKG",
            ".csv": "CSV",
            ".kml": "KML",
            ".tab": "MapInfo File"
        }

        self.extension_switch2 = {
            "ESRI Shapefile (*.shp *.SHP)": ".shp",
            "GeoJSON (*.geojson *.GEOJSON)": ".geojson",
            "GeoPackage (*.gpkg *.GPKG)": ".gpkg",
            "Comma Separated Value (*.csv *.CSV)": ".csv",
            "Keyhole Markup Language (*.kml *.KML)": ".kml",
            "Mapinfo TAB (*.tab *.TAB)": ".tab"
        }

        self.extension_switch_types = {
            ".shp": "ESRI Shapefile",
            ".geojson": "GeoJSON",
            ".gpkg": "GPKG",
            ".csv": "CSV",
            ".kml": "KML",
            ".tab": "MapInfo File"
        }

    def mouseClick(self):
        ''' Run click feature '''
        self.plugin_path = os.path.dirname(os.path.realpath(__file__))
        # Check if photo is loaded
        lys = self.canvas.layers()
        if len(lys) == 0:
            qgsutils.showUserAndLogMessage(
                u"Information: ", u"You need to upload the photo layer.")
            return
        # Folder viewer for local server
        folder = QgsApplication.qgisSettingsDirPath() + 'python/plugins/image_viewer/viewer'
        # Start local server in plugin folder
        openWebApp(folder)
        self.StartCefPython()
        # Create Timer is necessary for cefpython
        self.createTimer()

        f = open(self.plugin_path + "/layer_names.txt","r")

        for layer in lys:
            for x in f:
                if layer.name() in x:
                    self.checkLayer = True
                    self.mapTool = SelectTool(self.iface, parent=self, layer=layer)
                    self.iface.mapCanvas().setMapTool(self.mapTool)
                    return

        if self.checkLayer is False:
            qgsutils.showUserAndLogMessage(
                u"Information: ", u"You need to upload the photo layer.")

        return

    def ShowDialog(self, featuresId=None, layer=None):
        ''' Run dialog Geo360 '''
        self.featuresId = featuresId
        self.layer = layer

        if self.dlg1 is None:
            self.dlg1 = Geo360Dialog(self.iface, parent=self, featuresId=featuresId, layer=self.layer)
            self.dlg1.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint)
            self.dlg1.show()
        else:
            self.dlg1.ReloadView(self.featuresId)

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&Image Viewer'),
                action)
            self.iface.removeToolBarIcon(action)

    def run(self):
        """Run method that performs all the real work"""
        # Create the dialog with elements (after translation) and keep reference
        # Only create GUI ONCE in callback, so that it will only load when the plugin is started
        self.dlg.ok.setEnabled(True)
        self.dlg.closebutton.setEnabled(True)
        self.dlg.toolButtonImport.setEnabled(True)
        self.dlg.toolButtonOut.setEnabled(True)
        self.dlg.out.setText('')
        self.dlg.imp.setText('')
        self.dlg.show()

    def close(self):
        self.dlg.close()

    def toolButtonOut(self):
        typefiles = 'ESRI Shapefile (*.shp *.SHP);; GeoJSON (*.geojson *.GEOJSON);; GeoPackage (*.gpkg *.GPKG);; Comma Separated Value (*.csv *.CSV);; Keyhole Markup Language (*.kml *.KML);; Mapinfo TAB (*.tab *.TAB)'
        self.outputPath = QFileDialog.getSaveFileName(None, 'Save File',
                                                      os.path.join(os.path.join(os.path.expanduser('~')),
                                                                   'Desktop'), typefiles)
        self.extension_type = self.outputPath[1]
        self.outputPath = self.outputPath[0]
        if self.extension_type:
            self.extension2 = self.extension_switch2[self.extension_type]

        self.dlg.out.setText(self.outputPath)

    def toolButtonImport(self):
        self.directoryPhotos = QFileDialog.getExistingDirectory(None, 'Select a folder:',
                                                                os.path.join(os.path.join(os.path.expanduser('~')),
                                                                             'Desktop'), QFileDialog.ShowDirsOnly)
        self.selected_folder = self.directoryPhotos[:]#เอาหมด
        self.selected_folder = './' + os.path.basename(os.path.normpath(self.selected_folder)) + '/'#normpath ตัด // เป็น /
        self.dlg.imp.setText(self.directoryPhotos)

    def selectDir(self):
        title = 'Warning'
        msg = 'Please select a directory photos.'
        self.showMessage(title, msg, 'Warning')
        return True

    def selectOutp(self):
        title = 'Warning'
        msg = 'Please define output file location.'
        self.showMessage(title, msg, 'Warning')
        return True

    def noImageFound(self):
        title = 'Warning'
        msg = 'No image path found.'
        self.showMessage(title, msg, 'Warning')
        return True

    def ok(self):
        if self.dlg.imp.text() == '':
            if self.selectDir():
                return
        if not os.path.isdir(self.dlg.imp.text()):
            if self.selectDir():
                return
        if self.dlg.out.text() == '':
            if self.selectOutp():
                return
        if not os.path.isabs(self.dlg.out.text()):
            if self.selectOutp():
                return

        self.outputPath = self.dlg.out.text()
        self.directoryPhotos = self.dlg.imp.text()

        showMessageHide = True
        self.import_photos(self.directoryPhotos, self.outputPath, showMessageHide)

    def import_photos(self, directoryPhotos, outputPath, showMessageHide=True):
        self.plugin_path = os.path.dirname(os.path.realpath(__file__))
        self.showMessageHide = showMessageHide
        self.outputPath = outputPath
        self.directoryPhotos = directoryPhotos
        _ , self.extension = os.path.splitext(self.outputPath)#splitext เอาเฉพาะสกุลไฟล์
        basename = os.path.basename(self.outputPath)#basename เอาเฉพาะชื่อไฟล์+สกุลไฟล์
        self.myPhoto = basename[:-len(self.extension)]#แยกเอาแค่ชื่อไฟล์ vector
        self.outDirectoryPhotosGeoJSON = os.path.join(self.plugin_dir, 'tmp.geojson')
        f = open(self.plugin_path + "/layer_names.txt","r")
        self.equal_layer = False
        for x in f:
            if self.myPhoto in x:
                self.equal_layer = True
            else:
                pass
        if self.equal_layer is False:
            f = open(self.plugin_path + "/layer_names.txt","a")
            f.write(self.myPhoto + "\n")
            f.close()


        self.dlg.ok.setEnabled(False)
        self.dlg.closebutton.setEnabled(False)
        self.dlg.toolButtonImport.setEnabled(False)
        self.dlg.toolButtonOut.setEnabled(False)

        # get paths of photos
        extens = ['jpg', 'jpeg', 'JPG', 'JPEG']
        self.photos = []
        self.photos_names = []
        self.sorted_photos = []
        for root, dirs, files in os.walk(self.directoryPhotos):
            for name in files:
                if name.lower().endswith(tuple(extens)):
                    self.photos.append(os.path.join(root, name))
                    self.photos_names.append(name)

        self.initphotos = len(self.photos)
        self.sorted_photos = natsort.natsorted(self.photos, reverse=False)
      
        if self.initphotos == 0 and self.showMessageHide:
            title = 'Warning'
            msg = 'No photos.'
            self.showMessage(title, msg, 'Warning')
            self.dlg.ok.setEnabled(True)
            self.dlg.closebutton.setEnabled(True)
            self.dlg.toolButtonImport.setEnabled(True)
            self.dlg.toolButtonOut.setEnabled(True)
            return

        # Folder viewer for local server

        #self.canvas.setMapTool(self.toolMouseClick)

        self.truePhotosCount = 0
        self.out_of_extent_photos = 0

        self.Qpr_inst = QgsProject.instance()#เป็นการสรา้ง Object จาก class และเก็บไว้ในตัวแปร
        if platform.system()=='Darwin':
            self.layernamePhotos.append(self.myPhoto+' OGRGeoJSON Point')
        else:
            self.layernamePhotos.append(self.myPhoto)

        if platform.system() == 'Linux':
            self.outputPath = self.outputPath + self.extension
            self.extension = self.extension_switch[self.extension]
        else:
            self.extension = self.extension_switch[self.extension.lower()]

        self.exifread_module = False
        self.pil_module = False

        if CHECK_MODULE == '' and self.showMessageHide:
            self.showMessage('Python Modules', 'Please install python module "exifread" or "PIL".' , 'Warning')

        #self.import_photos_task('', '')
        self.call_import_photos()
        self.dlg.close()

    def refresh(self):  # Deselect features
        mc = self.canvas
        for layer in mc.layers():
            if layer.type() == layer.VectorLayer:
                layer.removeSelection()
        mc.refresh()

    def showMessage(self, title, msg, icon):
        if icon == 'Warning':
            icon = QMessageBox.Warning
        elif icon == 'Information':
            icon = QMessageBox.Information

        msgBox = QMessageBox()
        msgBox.setIcon(icon)
        msgBox.setWindowTitle(title)
        msgBox.setText(msg)
        msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint)
        msgBox.exec_()

    def completed(self, exception, result=None):

        geojson = {"type": "FeatureCollection",
                   "name": self.myPhoto,
                   "crs": {"type": "name", "properties": {"name": "crs:OGC:1.3:CRS84"}},
                   "features": self.geoPhotos}

        geofile = open(self.outDirectoryPhotosGeoJSON, 'w')#temp.geojson
        json.dump(geojson, geofile) #write file geojson to geofile
        geofile.close()
        del self.geoPhotos, geojson

        try:
            for layer in self.canvas.layers():
                if layer.publicSource() == self.outputPath:
                    self.Qpr_inst.instance().removeMapLayer(layer.id())
                    os.remove(self.outputPath)
        except:
            pass
        #เก็บข้อมูลรูปภาพเป็น layer เป็นลักษณะ vecter file format
        self.layerPhotos = QgsVectorLayer(self.outDirectoryPhotosGeoJSON, self.myPhoto, "ogr")
        QgsVectorFileWriter.writeAsVectorFormat(self.layerPhotos, self.outputPath, "utf-8",
                                                    QgsCoordinateReferenceSystem(self.layerPhotos.crs().authid()),
                                                    self.extension)
        self.layerPhotos_final = QgsVectorLayer(self.outputPath, self.myPhoto, "ogr")

        # clear temp.geojson file
        try:
            f = open(self.outDirectoryPhotosGeoJSON, 'r+')
            f.truncate(0)  # need '0' when using r+
        except:
            pass

        self.layerPhotos_final.setReadOnly(False)
        self.layerPhotos_final.reload()
        self.layerPhotos_final.triggerRepaint()

        try:
            xmin = min(self.lon)
            ymin = min(self.lat)
            xmax = max(self.lon)
            ymax = max(self.lat)
            self.canvas.zoomToSelected(self.layerPhotos_final)#ซูมจุด vector
            self.canvas.setExtent(QgsRectangle(xmin, ymin, xmax, ymax))#Sets the extent of the map canvas to the specified rectangle.
        except:
            pass

        ###########################################
        self.dlg.ok.setEnabled(True)
        self.dlg.closebutton.setEnabled(True)
        self.dlg.toolButtonImport.setEnabled(True)
        self.dlg.toolButtonOut.setEnabled(True)

        noLocationPhotosCounter = self.initphotos - self.truePhotosCount - self.out_of_extent_photos
        if (self.truePhotosCount == noLocationPhotosCounter == 0 or self.truePhotosCount == 0 ) and self.showMessageHide:
            title = 'Import Photos'
            msg = 'Import Completed.\n\nDetails:\n  No new photos were added.'
            self.showMessage(title, msg, 'Information')
            self.taskPhotos.destroyed()
            return
        elif ((self.truePhotosCount == self.initphotos) or ((noLocationPhotosCounter + self.truePhotosCount + self.out_of_extent_photos) == self.initphotos) )and self.showMessageHide:
            title = 'Import Photos'
            msg = 'Import Completed.\n\nDetails:\n  ' + str(
                int(self.truePhotosCount)) + ' photo(s) added without error.\n  ' + str(
                int(noLocationPhotosCounter)) + ' photo(s) skipped (because of missing location).\n  ' 
            self.showMessage(title, msg, 'Information')

        #add layer photo เป็นลำดับในลักษณะ Tree
        g = self.Qpr_inst.layerTreeRoot().insertGroup(0, self.myPhoto)
        self.Qpr_inst.addMapLayer(self.layerPhotos_final, False)#Add a layer to the map of loaded layers.
        nn = QgsLayerTreeLayer(self.layerPhotos_final)
        g.insertChildNode(0, nn)

    def stopped(self, task):
        QgsMessageLog.logMessage(
            'Task "{name}" was canceled'.format(
                name=task.description()),
            'ImportPhotos', Qgis.Info)

    def import_photos_task(self, task, wait_time):
        self.geoPhotos = []
        self.lon = []
        self.lat = []
        order = 0
        #names = []
        i = 0
        #self.sorted_names = []
        for count, imgpath in enumerate(self.sorted_photos):
            try:
                name = os.path.basename(imgpath)
                #names.append(name)
                RelPath = self.selected_folder + self.photos_names[count]#name.jpg
                if CHECK_MODULE == 'exifread' and not self.pil_module:
                    self.exifread_module = True
                    self.taskPhotos.setProgress(count / self.initphotos)
                    with open(imgpath, 'rb') as imgpathF:
                        tags = exifread.process_file(imgpathF, details=False)
                    if not tags.keys() & {"GPS GPSLongitude", "GPS GPSLatitude"}:
                        continue

                    lat, lon = self.get_exif_location(tags, "lonlat")
                    try:
                        if 'GPS GPSAltitude' in tags:
                            altitude = float(tags["GPS GPSAltitude"].values[0].num) / float(
                                tags["GPS GPSAltitude"].values[0].den)
                        else:
                            altitude = ''
                    except:
                        altitude = ''
                    order = order + 1

                    try:
                        dt1, dt2 = tags["EXIF DateTimeOriginal"].values.split()
                        date = dt1.replace(':', '/')
                        time_ = dt2
                        timestamp = dt1.replace(':', '-') + 'T' + time_
                    except:
                        try:
                            date = tags["GPS GPSDate"].values.replace(':', '/')
                            tt = [str(i) for i in tags["GPS GPSTimeStamp"].values]
                            time_ = "{:0>2}:{:0>2}:{:0>2}".format(tt[0], tt[1], tt[2])
                            timestamp = tags["GPS GPSDate"].values.replace(':', '-') + 'T' + time_
                        except:
                            date = ''
                            time_ = ''
                            timestamp = ''

                    try:
                        if 'GPS GPSImgDirection' in tags:
                            direction = float(tags["GPS GPSImgDirection"].values[0].num) / float(
                                tags["GPS GPSImgDirection"].values[0].den)
                        else:
                            direction = float(0)
                    except:
                        direction = ''

                    try:
                        if 'GPS GPSImgDirectionRef' in tags:
                            north = str(tags["GPS GPSImgDirectionRef"].values)
                        else:
                            north = ''
                    except:
                        north = ''

                    try:
                        if 'Image Make' in tags:
                            maker = tags['Image Make']
                        else:
                            maker = ''
                    except:
                        maker = ''

                    try:
                        if 'Image Model' in tags:
                            model = tags['Image Model']
                        else:
                            model = ''
                    except:
                        model = ''

                    try:
                        if 'Image ImageDescription' in tags:
                            title = tags['Image ImageDescription']
                        else:
                            title = ''
                    except:
                        title = ''

                    try:
                        if 'EXIF UserComment' in tags:
                            user_comm = tags['EXIF UserComment'].printable
                        else:
                            user_comm = ''
                    except:
                        user_comm = ''

                if CHECK_MODULE == 'PIL' and not self.exifread_module:
                    self.pil_module = True
                    a = {}
                    info = Image.open(imgpath)
                    info = info._getexif()

                    if info == None:
                        continue

                    for tag, value in info.items():
                        if TAGS.get(tag, tag) == 'GPSInfo' or TAGS.get(tag, tag) == 'DateTime' or TAGS.get(tag,
                                                                                                           tag) == 'DateTimeOriginal':
                            a[TAGS.get(tag, tag)] = value

                    if a == {}:
                        continue

                    if a['GPSInfo'] != {}:
                        if 1 and 2 and 3 and 4 in a['GPSInfo']:
                            lat = [float(x) / float(y) for x, y in a['GPSInfo'][2]]
                            latref = a['GPSInfo'][1]
                            lon = [float(x) / float(y) for x, y in a['GPSInfo'][4]]
                            lonref = a['GPSInfo'][3]

                            lat = lat[0] + lat[1] / 60 + lat[2] / 3600
                            lon = lon[0] + lon[1] / 60 + lon[2] / 3600

                            if latref == 'S':
                                lat = -lat
                            if lonref == 'W':
                                lon = -lon
                        else:
                            continue

                        order = order + 1
                        if 'DateTime' or 'DateTimeOriginal' in a:
                            if 'DateTime' in a:
                                dt1, dt2 = a['DateTime'].split()
                            if 'DateTimeOriginal' in a:
                                dt1, dt2 = a['DateTimeOriginal'].split()
                            date = dt1.replace(':', '/')
                            time_ = dt2
                            timestamp = dt1.replace(':', '-') + 'T' + time_

                        try:
                            if 6 in a['GPSInfo']:
                                if len(a['GPSInfo'][6]) > 1:
                                    mAltitude = float(a['GPSInfo'][6][0])
                                    mAltitudeDec = float(a['GPSInfo'][6][1])
                                    altitude = mAltitude / mAltitudeDec
                            else:
                                altitude = ''
                        except:
                            altitude = ''

                        try:
                            if 16 and 17 in a['GPSInfo']:
                                north = str(a['GPSInfo'][16])
                                direction = float(a['GPSInfo'][17][0]) / float(a['GPSInfo'][17][1])
                            else:
                                north = ''
                                direction = ''
                        except:
                            north = ''
                            direction = ''

                        maker = ''
                        model = ''
                        user_comm = ''
                        title = ''

                self.lon.append(lon)
                self.lat.append(lat)

                self.truePhotosCount = self.truePhotosCount + 1

                #self.sorted_names = natsort.natsorted(names, reverse=True)

                geo_info = {"type": "Feature",
                            "properties": {'Order': order, 'Name': name, 'Date': date, 'Time': time_,
                                           'Lon': lon,
                                           'Lat': lat, 'Altitude': altitude, 'North': north,
                                           'Direction': direction,
                                           'Camera Maker': str(maker), 'Camera Model': str(model), 'Title': str(title),
                                           'Comment': user_comm, 'Path': imgpath, 'RelPath': RelPath,
                                           'Timestamp': timestamp},
                            "geometry": {"coordinates": [lon, lat], "type": "Point"}}
                i = i + 1
                self.geoPhotos.append(geo_info)


                if self.taskPhotos.isCanceled():
                    self.stopped(self.taskPhotos)
                    self.taskPhotos.destroyed()
                    return None
            except:
                pass
        return True

    def call_import_photos(self):
        self.taskPhotos = QgsTask.fromFunction(u'ImportPhotos', self.import_photos_task,
                                 on_finished=self.completed, wait_time=4)

        QgsApplication.taskManager().addTask(self.taskPhotos)

    ######################################################
# based on http://www.codegists.com/snippet/python/exif_gpspy_snakeye_python

    def _get_if_exist(self, data, key):
        if key in data:
            return data[key]

        return None


    def _convert_to_degress(self, value):
        """
        Helper function to convert the GPS coordinates stored in the EXIF to degress in float format

        :param value:
        :type value: exifread.utils.Ratio
        :rtype: float
        """
        d = float(value.values[0].num) / float(value.values[0].den)
        m = float(value.values[1].num) / float(value.values[1].den)
        s = float(value.values[2].num) / float(value.values[2].den)

        return d + (m / 60.0) + (s / 3600.0)


    def get_exif_location(self, exif_data, lonlat):
        """
        Returns the latitude and longitude, if available, from the provided exif_data (obtained through get_exif_data above)
        """

        if lonlat=='lonlat':
            lat = ''
            lon = ''
            gps_latitude = self._get_if_exist(exif_data, 'GPS GPSLatitude')
            gps_latitude_ref = self._get_if_exist(exif_data, 'GPS GPSLatitudeRef')
            gps_longitude = self._get_if_exist(exif_data, 'GPS GPSLongitude')
            gps_longitude_ref = self._get_if_exist(exif_data, 'GPS GPSLongitudeRef')

            if gps_latitude and gps_latitude_ref and gps_longitude and gps_longitude_ref:
                lat = self._convert_to_degress(gps_latitude)
                if gps_latitude_ref.values[0] != 'N':
                    lat = 0 - lat

                lon = self._convert_to_degress(gps_longitude)
                if gps_longitude_ref.values[0] != 'E':
                    lon = 0 - lon

            return lat, lon
Пример #25
0
    def read2dm(self):
        try:
            crs = self.crs
        except(AttributeError):
            crs = QgsCoordinateReferenceSystem(
                3826, QgsCoordinateReferenceSystem.EpsgCrsId)
        meshFile = self.dlg.meshFileEdit.text()
        f = open(meshFile, 'r')
        nodeFields = QgsFields()
        nodeFields.append(QgsField("id", QVariant.Int))
        nodeFields.append(QgsField("z", QVariant.Double))
        nodePath = os.path.join(self.dlg.folderLineEdit.text(), 'Nodes.shp')
        nodeWriter = QgsVectorFileWriter(nodePath, 'UTF-8', nodeFields,
                                         QGis.WKBPoint, crs, 'ESRI Shapefile')

        data = f.readlines()
        NodeDict = dict()
        Regions = list()
        NodeStrings = list()
        oneString = list()
        for line in data:
            line = line.split()
            if line[0] == 'ND':
                NodeDict.update(
                    {int(line[1]): (float(line[2]), float(line[3]),
                                    float(line[4]))})
                geoString = ('POINT (' + line[2] + ' ' + line[3] + ')')
                feature = QgsFeature()
                feature.setGeometry(QgsGeometry.fromWkt(geoString))
                feature.setAttributes([int(line[1]), float(line[4])])
                nodeWriter.addFeature(feature)
            elif line[0] in meshType.keys():
                Regions.append(int(line[-1]))
            elif line[0] == 'NS':
                for i in range(1, len(line)):
                    oneString.append(fabs(int(line[i])))
                if int(line[-1]) < 0:
                    NodeStrings.append(oneString)
                    oneString = list()

        del nodeWriter
        Regions = list(set(Regions))
        Regions.sort()

        group = QgsProject.instance().layerTreeRoot().addGroup(
            os.path.basename(meshFile))

        regionWriters = list()
        fields = QgsFields()
        fields.append(QgsField("id", QVariant.Int))
        layerList = list()
        layerList.append(nodePath)
        for i in range(0, len(Regions)):
            layerName = 'Material' + str(Regions[i])
            path = os.path.join(self.dlg.folderLineEdit.text(),
                                layerName + '.shp')
            self.iface.messageBar().pushMessage(path)
            regionWriters.append(
                QgsVectorFileWriter(path, 'UTF-8', fields, QGis.WKBPolygon, crs,
                                    'ESRI Shapefile'))
            layerList.append(path)
        for line in data:
            line = line.split()
            if line[0] in meshType.keys():
                n = meshType[line[0]]
                geoString = 'POLYGON (('
                for k in range(2, 2+n):
                    Coor = NodeDict[int(line[k])]
                    geoString += (str(Coor[0]) + ' ' + str(Coor[1]) + ', ')
                Coor = NodeDict[int(line[2])]
                geoString += (str(Coor[0]) + ' ' + str(Coor[1]))
                geoString += '))'
                writer = regionWriters[int(line[-1])-1]

                feature = QgsFeature()
                feature.setGeometry(QgsGeometry().fromWkt(geoString))
                feature.setAttributes([int(line[1])])
                writer.addFeature(feature)

                if writer.hasError() != QgsVectorFileWriter.NoError:
                    self.iface.messageBar().pushMessage(
                        "Error when creating shapefile: ",
                        writer.errorMessage())

        for writer in regionWriters:
            del writer

        counter = 1
        for lineString in NodeStrings:
            path = os.path.join(self.dlg.folderLineEdit.text(),
                                'NodeString' + str(counter) + '.shp')
            writer = QgsVectorFileWriter(path, 'UTF-8', fields,
                                         QGis.WKBLineString, crs,
                                         'ESRI Shapefile')
            layerList.append(path)
            geoString = 'LINESTRING ('
            for i in range(0, len(lineString)):
                nodeCoor = NodeDict[lineString[i]]
                geoString += (str(nodeCoor[0]) + " " + str(nodeCoor[1]) + ", ")
            geoString = geoString[:-2] + ')'

            feature = QgsFeature()
            feature.setGeometry(QgsGeometry().fromWkt(geoString))
            feature.setAttributes([counter])
            writer.addFeature(feature)
            del writer
            counter += 1

        for i in range(0, len(layerList)):
            layer = QgsVectorLayer(
                layerList[i], QFileInfo(layerList[i]).baseName(), 'ogr')
            QgsMapLayerRegistry.instance().addMapLayer(layer, False)
            group.addLayer(layer)
            layer.reload()
Пример #26
0
    def testSubsetStringFids(self):
        """
          - tests that feature ids are stable even if a subset string is set
          - tests that the subset string is correctly set on the ogr layer event when reloading the data source (issue #17122)
        """

        tmpfile = os.path.join(self.basetestpath, 'subsetStringFids.sqlite')
        ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid'])
        lyr.CreateField(ogr.FieldDefn('type', ogr.OFTInteger))
        lyr.CreateField(ogr.FieldDefn('value', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(0)
        f.SetField(0, 1)
        f.SetField(1, 11)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (0 0)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(1)
        f.SetField(0, 1)
        f.SetField(1, 12)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (1 1)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(2)
        f.SetField(0, 1)
        f.SetField(1, 13)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (2 2)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(3)
        f.SetField(0, 2)
        f.SetField(1, 14)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (3 3)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(4)
        f.SetField(0, 2)
        f.SetField(1, 15)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (4 4)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(5)
        f.SetField(0, 2)
        f.SetField(1, 16)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (5 5)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl = QgsVectorLayer(tmpfile, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual([f.name() for f in vl.fields()], ['fid', 'type', 'value'])
        original_fields = vl.fields()

        vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr')
        self.assertTrue(vl.isValid())

        def run_checks():
            self.assertEqual([f.name() for f in vl.fields()], ['fid', 'type', 'value'])

            # expression
            req = QgsFeatureRequest()
            req.setFilterExpression("value=16")
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter fid
            req = QgsFeatureRequest()
            req.setFilterFid(5)
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter fids
            req = QgsFeatureRequest()
            req.setFilterFids([5])
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # check with subset of attributes
            req = QgsFeatureRequest()
            req.setFilterFids([5])
            req.setSubsetOfAttributes([2])
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes()[2], 16)
            self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter rect and expression
            req = QgsFeatureRequest()
            req.setFilterExpression("value=16 or value=14")
            req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5))
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter rect and fids
            req = QgsFeatureRequest()
            req.setFilterFids([3, 5])
            req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5))
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed
            req = QgsFeatureRequest()
            req.setSubsetOfAttributes([])
            it = vl.getFeatures(req)
            ids = []
            geoms = {}
            while it.nextFeature(f):
                ids.append(f.id())
                geoms[f.id()] = f.geometry().asWkt()
            self.assertCountEqual(ids, [3, 4, 5])
            self.assertEqual(geoms, {3: 'Point (3 3)', 4: 'Point (4 4)', 5: 'Point (5 5)'})

        run_checks()
        # Check that subset string is correctly set on reload
        vl.reload()
        run_checks()
Пример #27
0
    def test_generatedSignLine(self):

        # line layer
        testLayerA = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'),
                                    'test1', 'memory')
        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])
        testLineString2 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(1, 0), QgsPointXY(2, 0)])
        testLineString3 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(-1, 1)])
        testLineString4 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(1, 1), QgsPointXY(2, 1)])
        testProviderA.addAttributes([QgsField("GeometryID", QVariant.String)])
        testFieldsA = testProviderA.fields()
        testFeature1A = QgsFeature(testFieldsA)
        testFeature1A.setGeometry(testLineString1)
        testFeature1A.setAttributes(["Smith"])
        testFeature2A = QgsFeature(testFieldsA)
        testFeature2A.setGeometry(testLineString2)
        testFeature2A.setAttributes(["Jones"])
        testProviderA.addFeatures([testFeature1A, testFeature2A])
        testLayerA.reload()

        # point layer
        testLayerB = QgsVectorLayer(('Point?crs=epsg:27700&index=yes'),
                                    'test2', 'memory')
        testProviderB = testLayerB.dataProvider()

        testPoint1 = QgsPoint(0, 1)

        testProviderB.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("SignOrientation", QVariant.Int),
            QgsField("SignType_1", QVariant.Int),
            QgsField("SignType_2", QVariant.Int),
            QgsField("SignType_3", QVariant.Int),
            QgsField("SignType_4", QVariant.Int),
            QgsField("original_geom", QVariant.Geometry),
        ])
        testFieldsB = testProviderB.fields()

        testFeature2A = QgsFeature(testFieldsB)
        testFeature2A.setGeometry(testPoint1)
        testFeature2A.setAttributes(
            ["Alpha", 1, 1, None, None, None,
             testPoint1.asWkt()])
        testFeature2B = QgsFeature(testFieldsB)
        testFeature2B.setGeometry(testPoint1)
        testFeature2B.setAttributes(
            ["Beta", 2, 1, 1, None, None,
             testPoint1.asWkt()])
        testFeature2C = QgsFeature(testFieldsB)
        testFeature2C.setGeometry(testPoint1)
        testFeature2C.setAttributes(
            ["Gamma", 3, 1, 1, 1, None,
             testPoint1.asWkt()])
        testProviderB.addFeatures(
            [testFeature2A, testFeature2B, testFeature2C])
        testLayerB.reload()

        testLayerC = QgsVectorLayer(('Point?crs=epsg:27700&index=yes'),
                                    'test2', 'memory')
        testProviderC = testLayerC.dataProvider()

        testProviderC.addAttributes([QgsField("GeometryID", QVariant.String)])
        testFieldsC = testProviderC.fields()
        testFeature3A = QgsFeature(testFieldsC)
        testFeature3A.setGeometry(testPoint1)
        testFeature3A.setAttributes(["Zulu"])
        testProviderC.addFeatures([testFeature3A])
        testLayerC.reload()

        distanceForIcons = 3

        orientationToFeature, orientationInFeatureDirection, orientationAwayFromFeature, orientationOppositeFeatureDirection = self.testClass.getLineOrientationAtPoint(
            QgsPointXY(testPoint1), testFeature1A)

        print('orientationToFeature: {}'.format(orientationToFeature))
        self.assertEqual(orientationToFeature, 180.0)
        self.assertEqual(orientationInFeatureDirection, 90.0)
        self.assertEqual(orientationAwayFromFeature, 0.0)
        self.assertEqual(orientationOppositeFeatureDirection, 270.0)

        lineGeom = self.testClass.createLinewithPointAzimuthDistance(
            QgsPointXY(testPoint1), orientationToFeature, 5)
        self.assertEqual(lineGeom.length(), 5.0)

        # check creation of line - for feature with 1 sign
        platesInSign = self.testClass.getPlatesInSign(testFeature2A)
        nrPlatesInSign = len(platesInSign)
        self.assertEqual(nrPlatesInSign, 1)

        orientationList = self.testClass.getSignOrientation(
            testFeature2A, testLayerA)
        self.assertEqual(len(orientationList), 5)
        print('orientationList: {}'.format(orientationList))
        self.assertEqual(orientationList[1], 90.0)  # feature direction
        self.assertEqual(orientationList[2],
                         270.0)  # opposite feature direction
        self.assertEqual(orientationList[3], 180.0)  # facing feature
        self.assertEqual(orientationList[4], 0.0)  # facing away from feature

        lineGeom = self.testClass.getSignLine(testFeature2A, testLayerA,
                                              distanceForIcons)
        print('lineGeom: {}'.format(lineGeom.asWkt()))
        self.assertEqual(lineGeom.length(), 6)

        linePts = self.testClass.addPointsToSignLine(lineGeom, nrPlatesInSign,
                                                     distanceForIcons)
        #print ('newLineGeom: {}'.format(newLineGeom.asWkt()))
        #linePts = newLineGeom.asPolyline()
        self.assertEqual(len(linePts), 1)

        # check creation of line - for feature with 3 signs
        platesInSign = self.testClass.getPlatesInSign(testFeature2C)
        nrPlatesInSign = len(platesInSign)
        self.assertEqual(nrPlatesInSign, 3)

        orientationList = self.testClass.getSignOrientation(
            testFeature2C, testLayerA)
        self.assertEqual(len(orientationList), 5)
        self.assertEqual(orientationList[1], 90.0)

        lineGeom = self.testClass.getSignLine(testFeature2C, testLayerA,
                                              distanceForIcons)
        print('lineGeom: {}'.format(lineGeom.asWkt()))
        self.assertEqual(lineGeom.length(), 12)

        linePts = self.testClass.addPointsToSignLine(lineGeom, nrPlatesInSign,
                                                     distanceForIcons)
        #print ('newLineGeom: {}'.format(newLineGeom.asWkt()))
        #linePts = newLineGeom.asPolyline()
        self.assertEqual(len(linePts), 3)

        # check creation of line - for feature without signs field
        platesInSign = self.testClass.getPlatesInSign(testFeature3A)
        nrPlatesInSign = len(platesInSign)
        self.assertEqual(nrPlatesInSign, 0)

        orientationList = self.testClass.getSignOrientation(
            testFeature3A, testLayerA)
        self.assertEqual(len(orientationList), 5)
        self.assertIsNone(orientationList[0])

        lineGeom = self.testClass.getSignLine(testFeature3A, testLayerA,
                                              distanceForIcons)
        self.assertIsNone(lineGeom)

        newLineGeom = self.testClass.addPointsToSignLine(
            lineGeom, nrPlatesInSign, distanceForIcons)
        self.assertIsNone(lineGeom)

        # static function
        lineGeom = self.testClass1.finalSignLine(testFeature2C)
Пример #28
0
    def test_isThisTOMsLayer(self):

        #self.testData()
        testLayerA = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'),
                                    'test1', 'memory')
        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])
        testLineString2 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(1, 0), QgsPointXY(1, 1)])
        testLineString3 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(-1, 1)])
        testLineString4 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(1, 1), QgsPointXY(2, 1)])

        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("age", QVariant.Int),
            QgsField("size", QVariant.Double),
            QgsField("size2", QVariant.Double)
        ])
        testFieldsA = testProviderA.fields()
        """for field in testFields:
            print ('** {}'.format(field.name()))"""

        testFeature1 = QgsFeature(testFieldsA)
        testFeature1.setGeometry(testLineString1)
        testFeature1.setAttributes(["Smith", 20, 0.3])
        testProviderA.addFeatures([testFeature1])

        testFeature2 = QgsFeature(testFieldsA)
        testFeature2.setGeometry(testLineString2)
        testFeature2.setAttributes(["Blogs", 20, 0.3])
        testProviderA.addFeatures([testFeature2])

        # check field called "OpenDate" does not exist
        result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerA)
        self.assertFalse(result)

        # check field called "OpenDate" does exist but is NULL

        testLayerB = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'),
                                    'test2', 'memory')
        testProviderB = testLayerB.dataProvider()
        testProviderB.addAttributes([QgsField("OpenDate", QVariant.String)])
        testFieldsB = testProviderB.fields()
        testFeature3 = QgsFeature(testFieldsB)
        testFeature3.setGeometry(testLineString2)
        testProviderB.addFeatures([testFeature3])

        result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerB)
        self.assertFalse(result)

        # check field called "OpenDate" does exist but is not NULL
        testFeature3.setAttribute("OpenDate", 'Test')
        testProviderB.addFeatures([testFeature3])

        #print ('*************************** Count: {}'.format(testLayerB.featureCount()))
        testLayerB.reload()
        for field in testLayerB.fields():
            print('+++ field: {}'.format(field.name()))

        result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerB)
        self.assertTrue(result)
Пример #29
0
def checkoutLayer(repo, layername, bbox, ref=None):
    ref = ref or repo.HEAD
    newCommitId = repo.revparse(ref)
    trackedlayer = getTrackingInfoForGeogigLayer(repo.url, layername)
    if trackedlayer is not None:
        try:
            source = trackedlayer.source
            layer = QgsVectorLayer(source, layername, "ogr")
            assert layer.isValid()
        except:
            removeTrackedLayer(trackedlayer.source)
            trackedlayer = None
            filename = layerGeopackageFilename(layername, repo.title,
                                               repo.group)
            source = "%s|layername=%s" % (filename, layername)
    else:
        filename = layerGeopackageFilename(layername, repo.title, repo.group)
        source = "%s|layername=%s" % (filename, layername)

    if trackedlayer is None:
        repo.checkoutlayer(filename, layername, bbox, ref or repo.HEAD)
        addTrackedLayer(source, repo.url)
        try:
            layer = layerFromSource(source)
            iface.messageBar().pushMessage(
                "GeoGig",
                "Layer was already included in the current QGIS project",
                level=QgsMessageBar.INFO,
                duration=5)
        except WrongLayerSourceException:
            layer = loadLayerNoCrsDialog(source, layername, "ogr")
            QgsMapLayerRegistry.instance().addMapLayers([layer])
            iface.messageBar().pushMessage("GeoGig",
                                           "Layer correctly added to project",
                                           level=QgsMessageBar.INFO,
                                           duration=5)
    elif ref is not None:
        currentCommitId = getCommitId(source)
        try:
            layer = layerFromSource(source)
            wasLoaded = True
        except WrongLayerSourceException:
            layer = loadLayerNoCrsDialog(source, layername, "ogr")
            wasLoaded = False

        if newCommitId != currentCommitId:
            if hasLocalChanges(layer):
                raise HasLocalChangesError()
            filename, layername = namesFromLayer(layer)
            repo.checkoutlayer(filename, layername, bbox, ref)
            layer.reload()
            if not wasLoaded:
                QgsMapLayerRegistry.instance().addMapLayers([layer])
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer correctly added to project",
                    level=QgsMessageBar.INFO,
                    duration=5)
            else:
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer correctly updated to specified version",
                    level=QgsMessageBar.INFO,
                    duration=5)
                layer.triggerRepaint()
        else:
            if wasLoaded:
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer was already included in the current QGIS project",
                    level=QgsMessageBar.INFO,
                    duration=5)
            else:
                QgsMapLayerRegistry.instance().addMapLayers([layer])
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer correctly added to the current QGIS project",
                    level=QgsMessageBar.INFO,
                    duration=5)

    #repoWatcher.repoChanged.emit(repo)
    return layer
Пример #30
0
def points_along_line(layerout,
                      startpoint,
                      endpoint,
                      distance,
                      label,
                      layer,
                      selected_only=True,
                      force=False,
                      fo_fila=False,
                      divide=0,
                      decimal=2):
    """Adding Points along the line
    """

    crs = layer.crs().authid()

    # TODO check for virtual or shapelayer and set virt_layer according to it
    shape = False
    if shape:
        # define fields for feature attributes. A list of QgsField objects is needed
        fields = [
            QgsField("first", QVariant.Int),
            QgsField("second", QVariant.String)
        ]
        # create an instance of vector file writer, which will create the vector file.
        # Arguments:
        # 1. path to new file (will fail if exists already)
        # 2. encoding of the attributes
        # 3. field map
        # 4. geometry type - from WKBTYPE enum
        # 5. layer's spatial reference (instance of
        #    QgsCoordinateReferenceSystem) - optional
        # 6. driver name for the output file
        writer = QgsVectorFileWriter("my_shapes.shp", "CP1250", fields,
                                     Qgis.WKBPoint, crs, "ESRI Shapefile")
        if writer.hasError() != QgsVectorFileWriter.NoError:
            # fix_print_with_import
            print("Error when creating shapefile: ", writer.hasError())
        # add a feature
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10)))
        fet.setAttributes([1, "text"])
        writer.addFeature(fet)
        # delete the writer to flush features to disk (optional)
        del writer

        layer_type = "Shapefile"  # TODO Add Shapefile functionality here
    else:
        layer_type = "memory"

    virt_layer = QgsVectorLayer("Point?crs=%s" % crs, layerout, layer_type)
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()  # actually writes attributes

    units = layer.crs().mapUnits()

    unitname = QgsUnitTypes.toString(units)
    provider.addAttributes([
        QgsField("fid", QVariant.Int),
        QgsField("cng" + unitname, QVariant.Double)
    ])

    def get_features():
        """Getting the features
        """
        if selected_only:
            return layer.selectedFeatures()
        else:
            return layer.getFeatures()

    # Loop through all (selected) features
    for feature in get_features():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsMessageLog.logMessage("No geometry", "QChainage")
            continue

        features = create_points_at(startpoint, endpoint, distance, geom, fid,
                                    force, fo_fila, divide)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    proj = QgsProject.instance()
    proj.addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()

    # generic labeling properties
    if label:
        virt_layer.setCustomProperty("labeling", "pal")
        virt_layer.setCustomProperty("labeling/enabled", "true")
        virt_layer.setCustomProperty("labeling/fieldName", "cng")
        virt_layer.setCustomProperty("labeling/fontSize", "10")
        virt_layer.setCustomProperty("labeling/multiLineLabels", "true")
        virt_layer.setCustomProperty("labeling/formatNumbers", "true")
        virt_layer.setCustomProperty("labeling/decimals", decimal)
        virt_layer.setCustomProperty("labeling/Size", "5")
    # symbol = QgsMarkerSymbol.createSimple({"name": "capital"})
    # virt_layer.setRenderer(QgsSingleSymbolRenderer(symbol))
    virt_layer.triggerRepaint()
    return
Пример #31
0
    def testSubsetStringFids(self):
        """
          - tests that feature ids are stable even if a subset string is set
          - tests that the subset string is correctly set on the ogr layer event when reloading the data source (issue #17122)
        """

        tmpfile = os.path.join(self.basetestpath, 'subsetStringFids.sqlite')
        ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test',
                             geom_type=ogr.wkbPoint,
                             options=['FID=fid'])
        lyr.CreateField(ogr.FieldDefn('type', ogr.OFTInteger))
        lyr.CreateField(ogr.FieldDefn('value', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(0)
        f.SetField(0, 1)
        f.SetField(1, 11)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (0 0)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(1)
        f.SetField(0, 1)
        f.SetField(1, 12)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (1 1)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(2)
        f.SetField(0, 1)
        f.SetField(1, 13)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (2 2)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(3)
        f.SetField(0, 2)
        f.SetField(1, 14)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (3 3)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(4)
        f.SetField(0, 2)
        f.SetField(1, 15)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (4 4)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(5)
        f.SetField(0, 2)
        f.SetField(1, 16)
        f.SetGeometry(ogr.CreateGeometryFromWkt('Point (5 5)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl = QgsVectorLayer(tmpfile, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual([f.name() for f in vl.fields()],
                         ['fid', 'type', 'value'])
        original_fields = vl.fields()

        vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr')
        self.assertTrue(vl.isValid())

        def run_checks():
            self.assertEqual([f.name() for f in vl.fields()],
                             ['fid', 'type', 'value'])

            # expression
            req = QgsFeatureRequest()
            req.setFilterExpression("value=16")
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()],
                             ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter fid
            req = QgsFeatureRequest()
            req.setFilterFid(5)
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()],
                             ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter fids
            req = QgsFeatureRequest()
            req.setFilterFids([5])
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()],
                             ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # check with subset of attributes
            req = QgsFeatureRequest()
            req.setFilterFids([5])
            req.setSubsetOfAttributes([2])
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes()[2], 16)
            self.assertEqual([field.name() for field in f.fields()],
                             ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter rect and expression
            req = QgsFeatureRequest()
            req.setFilterExpression("value=16 or value=14")
            req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5))
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()],
                             ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # filter rect and fids
            req = QgsFeatureRequest()
            req.setFilterFids([3, 5])
            req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5))
            it = vl.getFeatures(req)
            f = QgsFeature()
            self.assertTrue(it.nextFeature(f))
            self.assertEqual(f.id(), 5)
            self.assertEqual(f.attributes(), [5, 2, 16])
            self.assertEqual([field.name() for field in f.fields()],
                             ['fid', 'type', 'value'])
            self.assertEqual(f.geometry().asWkt(), 'Point (5 5)')

            # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed
            req = QgsFeatureRequest()
            req.setSubsetOfAttributes([])
            it = vl.getFeatures(req)
            ids = []
            geoms = {}
            while it.nextFeature(f):
                ids.append(f.id())
                geoms[f.id()] = f.geometry().asWkt()
            self.assertCountEqual(ids, [3, 4, 5])
            self.assertEqual(geoms, {
                3: 'Point (3 3)',
                4: 'Point (4 4)',
                5: 'Point (5 5)'
            })

        run_checks()
        # Check that subset string is correctly set on reload
        vl.reload()
        run_checks()
Пример #32
0
def points_along_line(layerout,
                      startpoint,
                      endpoint,
                      distance,
                      label,
                      layer,
                      selected_only=True,
                      force=False,
                      divide=0):
    """Adding Points along the line
    """
    # Create a new memory layer and add a distance attribute self.layerNameLine
    #layer_crs = virt_layer.setCrs(layer.crs())
    virt_layer = QgsVectorLayer("Point?crs=%s" % layer.crs().authid(),
                                layerout, "memory")
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()  # actually writes attributes
    units = layer.crs().mapUnits()
    unit_dic = {
        QGis.Degrees: 'Degrees',
        QGis.Meters: 'Meters',
        QGis.Feet: 'Feet',
        QGis.UnknownUnit: 'Unknown'
    }
    unit = unit_dic.get(units, 'Unknown')
    provider.addAttributes([QgsField("fid", QVariant.Int)])
    provider.addAttributes([QgsField("cng_(" + unit + ")", QVariant.Int)])

    def get_features():
        """Getting the features
        """
        if selected_only:
            return layer.selectedFeatures()
        else:
            return layer.getFeatures()

    # Loop through all (selected) features
    for feature in get_features():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsMessageLog.logMessage("No geometry", "QChainage")
            continue

        features = create_points_at(startpoint, endpoint, distance, geom, fid,
                                    force, divide)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()

    #from here Add labeling
    #generic labeling properties
    if label:
        virt_layer.setCustomProperty("labeling", "pal")
        virt_layer.setCustomProperty("labeling/enabled", "true")
        virt_layer.setCustomProperty("labeling/fieldName",
                                     "cng_(" + unit + ")")
        virt_layer.setCustomProperty("labeling/fontSize", "10")
        virt_layer.setCustomProperty("labeling/multiLineLabels", "true")

        #virt_layer.setCustomProperty("labeling/Size", "5")
    # symbol = QgsMarkerSymbolV2.createSimple({"name": "capital"})
    # virt_layer.setRendererV2(QgsSingleSymbolRendererV2(symbol))
    virt_layer.triggerRepaint()
    return