コード例 #1
0
    def testOverwriteGPKG(self):
        """Test that overwriting the same origin GPKG file works only if the layername is different"""

        # Prepare test data
        ml = QgsVectorLayer('Point?field=firstfield:int&field=secondfield:int', 'test', 'memory')
        provider = ml.dataProvider()
        ft = QgsFeature()
        ft.setAttributes([4, -10])
        provider.addFeatures([ft])
        filehandle, filename = tempfile.mkstemp('.gpkg')

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml,
            filename,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

        # Real test
        vl = QgsVectorLayer("%s|layername=test" % filename, 'src_test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 1)

        # This must fail
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            vl,
            filename,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.ErrCreateDataSource)
        self.assertEqual(error_message, 'Cannot overwrite a OGR layer in place')

        options.layerName = 'test2'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            vl,
            filename,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)
    def save_as_dbf(self, raster_source) -> bool:
        """Save/export a copy of the RAT to path"""

        # Add .VAT: .DBF is added by the exporter
        if not raster_source.upper().endswith('.VAT'):
            raster_source = raster_source + '.vat'

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'ESRI Shapefile'
        options.layerOptions = ['SHPT=NULL']

        writer = QgsVectorFileWriter.create(raster_source, self.qgis_fields(),
                                            QgsWkbTypes.Unknown,
                                            QgsCoordinateReferenceSystem(),
                                            QgsCoordinateTransformContext(),
                                            options)

        self.path = raster_source + '.dbf'

        rat_log('RAT saved as DBF for layer %s' % raster_source)

        return writer.addFeatures(self.qgis_features())
コード例 #3
0
    def testWriterWithExtent(self):
        """Check writing using extent filter."""
        source_file = os.path.join(TEST_DATA_DIR, 'points.shp')
        source_layer = QgsVectorLayer(source_file, 'Points', 'ogr')
        self.assertTrue(source_layer.isValid())

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'ESRI Shapefile'
        options.filterExtent = QgsRectangle(-111, 26, -96, 38)

        dest_file_name = os.path.join(str(QDir.tempPath()), 'extent_no_transform.shp')
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            source_layer,
            dest_file_name,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

        # Open result and check
        created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr')
        features = [f for f in created_layer.getFeatures()]
        self.assertEqual(len(features), 5)
        for f in features:
            self.assertTrue(f.geometry().intersects(options.filterExtent))
コード例 #4
0
    def testWriterWithExtentAndReprojection(self):
        """Check writing using extent filter with reprojection."""
        source_file = os.path.join(TEST_DATA_DIR, 'points.shp')
        source_layer = QgsVectorLayer(source_file, 'Points', 'ogr')
        self.assertTrue(source_layer.isValid())

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'ESRI Shapefile'
        options.filterExtent = QgsRectangle(-12511460, 3045157, -10646621, 4683497)
        options.ct = QgsCoordinateTransform(source_layer.crs(), QgsCoordinateReferenceSystem.fromEpsgId(3785), QgsProject.instance())

        dest_file_name = os.path.join(str(QDir.tempPath()), 'extent_transform.shp')
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            source_layer,
            dest_file_name,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

        # Open result and check
        created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr')
        features = [f for f in created_layer.getFeatures()]
        self.assertEqual(len(features), 5)
        for f in features:
            self.assertTrue(f.geometry().intersects(options.filterExtent))
コード例 #5
0
ファイル: utils.py プロジェクト: vvkond/CutTool_v3
def memoryToShp(layer, scheme, layerName):
    ln = layerName.replace('/', '-').replace('\\', '-').replace(
        '>', '-').replace('<', '-').replace(' ', '')[:MAX_FILE_NAME_SIZE - 26]
    layerFile = u'{0}_{1}'.format(
        ln, time.strftime('%d_%m_%Y_%H_%M_%S', time.localtime()))

    (prjPath, prjExt) = os.path.splitext(QgsProject.instance().fileName())

    layerFileName = prjPath + u'_{0}.gpkg'.format(scheme)

    options = QgsVectorFileWriter.SaveVectorOptions()
    if os.path.exists(layerFileName):
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    options.layerName = layerFile
    _writer = QgsVectorFileWriter.writeAsVectorFormat(layer, layerFileName,
                                                      options)
    if _writer and _writer[0] > 0:
        QgsMessageLog.logMessage(
            u"Layer write:{} error: {}".format(layer.name(), _writer),
            "QgisPDS.error", Qgis.Critical)

    layerName = createLayerName(layerName)
    layerFileName = layerFileName + '|layername=' + layerFile
    return QgsVectorLayer(layerFileName, layerName, 'ogr')
コード例 #6
0
    def testCreateDGN(self):
        ml = QgsVectorLayer('Point?crs=epsg:4326', 'test', 'memory')
        provider = ml.dataProvider()
        feat = QgsFeature()
        feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10)))
        provider.addFeatures([feat])

        filename = os.path.join(str(QDir.tempPath()), 'testCreateDGN.dgn')
        crs = QgsCoordinateReferenceSystem()
        crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
        rc, errmsg = QgsVectorFileWriter.writeAsVectorFormat(ml, filename, 'utf-8', crs, 'DGN')

        # open the resulting file
        vl = QgsVectorLayer(filename, '', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 1)
        del vl

        # append
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'DGN'
        options.layerName = 'test'
        options.actionOnExistingFile = QgsVectorFileWriter.AppendToLayerNoNewFields
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml,
            filename,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

        # open the resulting file
        vl = QgsVectorLayer(filename, '', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 2)
        del vl

        os.unlink(filename)
コード例 #7
0
    def _save_layer_to_file(layer: QgsVectorLayer, output_path: Path) -> Path:
        """ Save layer to file"""
        output_file = output_path / f'{layer.name().replace(" ", "")}.csv'
        LOGGER.debug(f'Saving layer to a file {output_file.name}')

        converter = CsvFieldValueConverter(layer)

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = "csv"
        options.fileEncoding = "utf-8"
        options.layerOptions = ["SEPARATOR=COMMA"]
        options.fieldValueConverter = converter

        # noinspection PyCallByClass
        writer_, msg = QgsVectorFileWriter.writeAsVectorFormatV2(
            layer, str(output_file),
            QgsProject.instance().transformContext(), options)

        if msg:
            raise ProcessInterruptedException(
                tr('Process ended'),
                bar_msg=bar_msg(
                    tr('Exception occurred during data extraction: {}', msg)))
        return output_file
コード例 #8
0
ファイル: functions.py プロジェクト: Riverscapes/RIPTPlugin
def create_geopackage_table(geometry_type, table_name, geopackage_path,
                            full_path, field_tuple_list):
    """
        Creates tables in existing or new geopackages
        geometry_type (string):  NoGeometry, Polygon, Linestring, Point, etc...
        table_name (string): Name for the new table
        geopackage_path (string): full path to the geopackage i.e., dir/package.gpkg
        full_path (string): full path including the layer i.e., dir/package.gpkg|layername=layer
        field_tuple_list (list): a list of tuples as field name and QVariant field types i.e., [('my_field', QVarient.Double)]
        """
    memory_layer = QgsVectorLayer(geometry_type, "memory_layer", "memory")
    fields = []
    for field_tuple in field_tuple_list:
        field = QgsField(field_tuple[0], field_tuple[1])
        fields.append(field)
    memory_layer.dataProvider().addAttributes(fields)
    memory_layer.updateFields()
    options = QgsVectorFileWriter.SaveVectorOptions()
    options.layerName = table_name
    options.driverName = 'GPKG'
    if os.path.exists(geopackage_path):
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    QgsVectorFileWriter.writeAsVectorFormat(memory_layer, geopackage_path,
                                            options)
コード例 #9
0
    def testSetBufferedGroupsAfterAutomaticGroups(self):

        ml = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer&field=int2:integer', 'test',
            'memory')

        # Load 2 layer from a geopackage
        d = QTemporaryDir()
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'layer_a'
        err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
            ml, os.path.join(d.path(), 'test_EditBufferGroup.gpkg'),
            QgsCoordinateTransformContext(), options)

        options.layerName = 'layer_b'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
        err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
            ml, os.path.join(d.path(), 'test_EditBufferGroup.gpkg'),
            QgsCoordinateTransformContext(), options)

        layer_a = QgsVectorLayer(newFileName + '|layername=layer_a')
        self.assertTrue(layer_a.isValid())
        layer_b = QgsVectorLayer(newFileName + '|layername=layer_b')
        self.assertTrue(layer_b.isValid())

        project = QgsProject()
        project.addMapLayers([layer_a, layer_b, ml])

        project.setTransactionMode(Qgis.TransactionMode.AutomaticGroups)
        project.setTransactionMode(Qgis.TransactionMode.BufferedGroups)

        project.startEditing()
        success, rollbackErrors = project.rollBack(True)

        self.assertTrue(success)
コード例 #10
0
    def response_shp_mode(self, request):
        """
        Download Shapefile of data

        :param request: Http Django request object
        :return: http response with attached file
        """

        if not self.layer.download:
            return HttpResponseForbidden()

        tmp_dir = tempfile.TemporaryDirectory()

        filename = self._build_download_filename(request)

        # Apply filter backends, store original subset string
        qgs_request = QgsFeatureRequest()
        original_subset_string = self.metadata_layer.qgis_layer.subsetString()
        if hasattr(self, 'filter_backends'):
            for backend in self.filter_backends:
                backend().apply_filter(request, self.metadata_layer, qgs_request, self)

        save_options = QgsVectorFileWriter.SaveVectorOptions()
        save_options.driverName = 'ESRI Shapefile'
        save_options.fileEncoding = 'utf-8'

        # Make a selection based on the request
        self._selection_responde_download_mode(qgs_request, save_options)

        file_path = os.path.join(tmp_dir.name, filename)
        error_code, error_message = QgsVectorFileWriter.writeAsVectorFormatV2(
            self.metadata_layer.qgis_layer,
            file_path,
            self.metadata_layer.qgis_layer.transformContext(),
            save_options
        )

        # Restore the original subset string and select no features
        self.metadata_layer.qgis_layer.selectByIds([])
        self.metadata_layer.qgis_layer.setSubsetString(original_subset_string)

        if error_code != QgsVectorFileWriter.NoError:
            tmp_dir.cleanup()
            return HttpResponse(status=500, reason=error_message)

        # Check for extra fields to add
        self._add_extrafields(request, file_path, filename)

        filenames = ["{}{}".format(filename, ftype)
                     for ftype in self.shp_extentions]

        zip_filename = "{}.zip".format(filename)

        # Open BytesIO to grab in-memory ZIP contents
        s = io.BytesIO()

        # The zip compressor
        zf = zipfile.ZipFile(s, "w")

        for fpath in filenames:

            # Add file, at correct path
            ftoadd = os.path.join(tmp_dir.name, fpath)
            if os.path.exists(ftoadd):
                zf.write(ftoadd, fpath)

        # Must close zip for all contents to be written
        zf.close()
        tmp_dir.cleanup()

        # Grab ZIP file from in-memory, make response with correct MIME-type
        response = HttpResponse(
            s.getvalue(), content_type="application/x-zip-compressed")
        response['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
        response.set_cookie('fileDownload', 'true')
        return response
コード例 #11
0
def to_layer(features, crs, encoding, geom_type, layer_type, path):
    first_feat = features[0]
    fields = first_feat.fields()
    layer = None
    if layer_type == 'memory':
        layer = QgsVectorLayer(geom_type + '?crs=' + crs.authid(), path,
                               "memory")
        pr = layer.dataProvider()
        pr.addAttributes(fields.toList())
        layer.updateFields()
        layer.startEditing()
        pr.addFeatures(features)
        layer.commitChanges()

    elif layer_type == 'shapefile':

        wkbTypes = {
            'Point': QgsWkbTypes.Point,
            'Linestring': QgsWkbTypes.LineString,
            'Polygon': QgsWkbTypes.Polygon
        }
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = "ESRI Shapefile"
        options.fileEncoding = encoding
        file_writer = QgsVectorFileWriter.create(
            path, fields, wkbTypes[geom_type], crs,
            QgsCoordinateTransformContext(), options)

        if file_writer.hasError() != QgsVectorFileWriter.NoError:
            print("Error when creating shapefile: ",
                  file_writer.errorMessage())
        del file_writer
        layer = QgsVectorLayer(path, ntpath.basename(path)[:-4], "ogr")
        pr = layer.dataProvider()
        layer.startEditing()
        pr.addFeatures(features)
        layer.commitChanges()

    elif layer_type == 'postgis':

        # this is needed to load the table later
        # uri = connstring + """ type=""" + geom_types[geom_type] + """ table=\"""" + schema_name + """\".\"""" + table_name + """\" (geom) """

        connstring, schema_name, table_name = path
        uri = connstring + """ type=""" + geom_type + """ table=\"""" + schema_name + """\".\"""" + table_name + """\" (geom) """
        crs_id = crs.postgisSrid()
        try:
            con = psycopg2.connect(connstring)
            cur = con.cursor()
            create_query = cur.mogrify(
                """DROP TABLE IF EXISTS "%s"."%s"; CREATE TABLE "%s"."%s"( geom geometry(%s, %s))""",
                (AsIs(schema_name), AsIs(table_name), AsIs(schema_name),
                 AsIs(table_name), geom_type, AsIs(crs_id)))
            cur.execute(create_query)
            con.commit()
            post_q_flds = {
                2: 'bigint',
                6: 'numeric',
                1: 'bool',
                'else': 'text',
                4: 'numeric'
            }
            for f in fields:
                f_type = f.type()
                if f_type not in [2, 6, 1]:
                    f_type = 'else'
                attr_query = cur.mogrify(
                    """ALTER TABLE "%s"."%s" ADD COLUMN "%s" %s""",
                    (AsIs(schema_name), AsIs(table_name), AsIs(
                        f.name()), AsIs(post_q_flds[f_type])))
                cur.execute(attr_query)
                con.commit()
            field_names = ",".join(['"' + f.name() + '"' for f in fields])
            for feature in features:
                attrs = [i if i else None for i in feature.attributes()]
                insert_query = cur.mogrify(
                    """INSERT INTO "%s"."%s" (%s, geom) VALUES %s, ST_GeomFromText(%s,%s))""",
                    (AsIs(schema_name), AsIs(table_name), AsIs(field_names),
                     tuple(attrs), feature.geometry().asWkt(), AsIs(crs_id)))
                idx = insert_query.find(b', ST_GeomFromText') - 1
                insert_query = insert_query[:idx] + insert_query[(idx + 1):]
                cur.execute(insert_query)
                con.commit()
            pkey_query = cur.mogrify(
                """ALTER TABLE "%s"."%s" DROP COLUMN IF EXISTS seg_id; ALTER TABLE "%s"."%s" ADD COLUMN seg_id serial PRIMARY KEY NOT NULL;""",
                (AsIs(schema_name), AsIs(table_name), AsIs(schema_name),
                 AsIs(table_name)))
            cur.execute(pkey_query)
            con.commit()
            con.close()
            layer = QgsVectorLayer(uri, table_name, 'postgres')
        except psycopg2.DatabaseError as e:
            # fix_print_with_import
            print(e)

    return layer
コード例 #12
0
ファイル: post_iii_rch.py プロジェクト: akakayk/QSWATMOD2
def read_mf_recharge_dates(self):
    QSWATMOD_path_dict = self.dirs_and_paths()
    stdate, eddate, stdate_warmup, eddate_warmup = self.define_sim_period()
    wd = QSWATMOD_path_dict['SMfolder']
    startDate = stdate.strftime("%m-%d-%Y")
    
    # Create swatmf_results tree inside 
    root = QgsProject.instance().layerTreeRoot()
    if root.findGroup("swatmf_results"):
        swatmf_results = root.findGroup("swatmf_results")
    else:
        swatmf_results = root.insertGroup(0, "swatmf_results")

    input1 = QgsProject.instance().mapLayersByName("mf_grid (MODFLOW)")[0]
    provider = input1.dataProvider()

    if self.dlg.checkBox_recharge.isChecked() and self.dlg.radioButton_mf_results_d.isChecked():
        filename = "swatmf_out_MF_recharge"

        # Open "swatmf_out_MF_recharge" file
        y = ("MODFLOW", "--Calculated", "daily") # Remove unnecssary lines
        with open(os.path.join(wd, filename), "r") as f:
            data = [x.strip() for x in f if x.strip() and not x.strip().startswith(y)]  # Remove blank lines
        date = [x.strip().split() for x in data if x.strip().startswith("Day:")] # Collect only lines with dates
        onlyDate = [x[1] for x in date] # Only date
        # data1 = [x.split() for x in data] # make each line a list
        sdate = datetime.datetime.strptime(startDate, "%m-%d-%Y")  # Change startDate format
        dateList = [(sdate + datetime.timedelta(days = int(i)-1)).strftime("%m-%d-%Y") for i in onlyDate]
        self.dlg.comboBox_mf_results_sdate.clear()
        self.dlg.comboBox_mf_results_sdate.addItems(dateList)
        self.dlg.comboBox_mf_results_edate.clear()
        self.dlg.comboBox_mf_results_edate.addItems(dateList)
        self.dlg.comboBox_mf_results_edate.setCurrentIndex(len(dateList)-1)

        # Copy mf_grid shapefile to swatmf_results tree
        name_ext = "mf_rch_daily.gpkg"
        output_dir = QSWATMOD_path_dict['SMshps']

        # Check if there is an exsting mf_recharge shapefile
        if not any(lyr.name() == ("mf_rch_daily") for lyr in list(QgsProject.instance().mapLayers().values())):
            mf_rch_shapfile = os.path.join(output_dir, name_ext)
            # overwrite option
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
            QgsVectorFileWriter.writeAsVectorFormat(input1, mf_rch_shapfile, options)
            layer = QgsVectorLayer(mf_rch_shapfile, '{0}'.format("mf_rch_daily"), 'ogr')
            # Put in the group
            root = QgsProject.instance().layerTreeRoot()
            swatmf_results = root.findGroup("swatmf_results")   
            QgsProject.instance().addMapLayer(layer, False)
            swatmf_results.insertChildNode(0, QgsLayerTreeLayer(layer))

            msgBox = QMessageBox()
            msgBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png'))
            msgBox.setWindowTitle("Created!")
            msgBox.setText("'mf_rch_daily.gpkg' file is created in 'swatmf_results' group!")
            msgBox.exec_()

    elif self.dlg.checkBox_recharge.isChecked() and self.dlg.radioButton_mf_results_m.isChecked():
        filename = "swatmf_out_MF_recharge_monthly"

        # Open "swatmf_out_MF_recharge" file
        y = ("Monthly") # Remove unnecssary lines
        with open(os.path.join(wd, filename), "r") as f:
            data = [x.strip() for x in f if x.strip() and not x.strip().startswith(y)] # Remove blank lines
        date = [x.strip().split() for x in data if x.strip().startswith("month:")] # Collect only lines with dates
        onlyDate = [x[1] for x in date] # Only date
        # data1 = [x.split() for x in data] # make each line a list
        dateList = pd.date_range(startDate, periods=len(onlyDate), freq='M').strftime("%b-%Y").tolist()
        self.dlg.comboBox_mf_results_sdate.clear()
        self.dlg.comboBox_mf_results_sdate.addItems(dateList)
        self.dlg.comboBox_mf_results_edate.clear()
        self.dlg.comboBox_mf_results_edate.addItems(dateList)
        self.dlg.comboBox_mf_results_edate.setCurrentIndex(len(dateList)-1)

        # Copy mf_grid shapefile to swatmf_results tree
        name_ext = "mf_rch_monthly.gpkg"
        output_dir = QSWATMOD_path_dict['SMshps']

        # Check if there is an exsting mf_recharge shapefile
        if not any(lyr.name() == ("mf_rch_monthly") for lyr in list(QgsProject.instance().mapLayers().values())):
            mf_rch_shapfile = os.path.join(output_dir, name_ext)
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
            QgsVectorFileWriter.writeAsVectorFormat(input1, mf_rch_shapfile, options)
            layer = QgsVectorLayer(mf_rch_shapfile, '{0}'.format("mf_rch_monthly"), 'ogr')

            # Put in the group
            root = QgsProject.instance().layerTreeRoot()
            swatmf_results = root.findGroup("swatmf_results")   
            QgsProject.instance().addMapLayer(layer, False)
            swatmf_results.insertChildNode(0, QgsLayerTreeLayer(layer))

            msgBox = QMessageBox()
            msgBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png'))
            msgBox.setWindowTitle("Created!")
            msgBox.setText("'mf_rch_monthly.gpkg' file is created in 'swatmf_results' group!")
            msgBox.exec_()      

    elif self.dlg.checkBox_recharge.isChecked() and self.dlg.radioButton_mf_results_y.isChecked():
        filename = "swatmf_out_MF_recharge_yearly"

        # Open "swatmf_out_MF_recharge" file
        y = ("Yearly") # Remove unnecssary lines
        with open(os.path.join(wd, filename), "r") as f:
            data = [x.strip() for x in f if x.strip() and not x.strip().startswith(y)] # Remove blank lines
        date = [x.strip().split() for x in data if x.strip().startswith("year:")] # Collect only lines with dates
        onlyDate = [x[1] for x in date] # Only date
        # data1 = [x.split() for x in data] # make each line a list
        dateList = pd.date_range(startDate, periods = len(onlyDate), freq = 'A').strftime("%Y").tolist()
        self.dlg.comboBox_mf_results_sdate.clear()
        self.dlg.comboBox_mf_results_sdate.addItems(dateList)
        self.dlg.comboBox_mf_results_edate.clear()
        self.dlg.comboBox_mf_results_edate.addItems(dateList)
        self.dlg.comboBox_mf_results_edate.setCurrentIndex(len(dateList)-1)

        # Copy mf_grid shapefile to swatmf_results tree
        name_ext = "mf_rch_yearly.gpkg"
        output_dir = QSWATMOD_path_dict['SMshps']

        # Check if there is an exsting mf_recharge shapefile
        if not any(lyr.name() == ("mf_rch_yearly") for lyr in list(QgsProject.instance().mapLayers().values())):
            mf_rch_shapfile = os.path.join(output_dir, name_ext)
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
            QgsVectorFileWriter.writeAsVectorFormat(input1, mf_rch_shapfile, options)
            layer = QgsVectorLayer(mf_rch_shapfile, '{0}'.format("mf_rch_yearly"), 'ogr')

            # Put in the group
            root = QgsProject.instance().layerTreeRoot()
            swatmf_results = root.findGroup("swatmf_results")   
            QgsProject.instance().addMapLayer(layer, False)
            swatmf_results.insertChildNode(0, QgsLayerTreeLayer(layer))

            msgBox = QMessageBox()
            msgBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png'))
            msgBox.setWindowTitle("Created!")
            msgBox.setText("'mf_rch_yearly.gpkg' file is created in 'swatmf_results' group!")
            msgBox.exec_()      

    else:
        self.dlg.comboBox_mf_results_sdate.clear()
コード例 #13
0
    def on_btnRun_clicked(self):
                
        if self.inputfile == '':
            QMessageBox.critical(self,'Map Creator',
                                 'Please specify input coordinate file.')
            return
        
        if self.outputfile == '':
            QMessageBox.critical(self,'Map Creator',
                                 'Please specify output shapefile.')
            return
        
        self.setCursor(Qt.WaitCursor)

        #Open coordinate input file
        f = open(self.inputfile, 'r')
        lines = f.readlines()
        f.close()
        header = lines[0].split(',')[0]
        totfeat = len(lines) - 1
        lines.pop(0)
        lines.reverse() 
        
        #Create vector layer
        basename = os.path.basename(self.outputfile)
        vlayer = QgsVectorLayer("Polygon", basename, "memory")
        vprovider = vlayer.dataProvider()
        fld = QgsField(header,QVariant.String)
        flds = QgsFields()
        flds.append(fld)
        vprovider.addAttributes([fld])
        vlayer.startEditing()
                
        hull = []
        for cnt, line in enumerate(lines):
            line = line.rstrip().split(',')
            numcoords = int((len(line) - 1) / 2)
            hull[:] = []
            geom = QgsGeometry()
            feat = QgsFeature()
            feat.setFields(flds)
            for i in range(numcoords):
                hull.append(QgsPointXY(float(line[i*2+1]),float(line[i*2+2])))
            geom = geom.fromMultiPointXY(hull)
            geom = geom.convexHull()
            feat.setGeometry(geom)
            feat.setAttribute(header,str(line[0]))
            result = vlayer.addFeature(feat)
            if not result:
                self.setCursor(Qt.ArrowCursor)
                QMessageBox.critical(self,'Map Creator', 'Processing error.')
                return
            self.ui.ProgressBar.setValue(float(cnt+1)/float(totfeat) * 100.0)
            QApplication.processEvents()  
        vlayer.commitChanges()
        vlayer.updateExtents()
        
        #Write the output shapefile
        if os.path.exists(self.outputfile):
            QgsVectorFileWriter.deleteShapeFile(self.outputfile)
        voptions = QgsVectorFileWriter.SaveVectorOptions()
        voptions.driverName = 'ESRI Shapefile'
        voptions.fileEncoding = 'utf-8'
        result = QgsVectorFileWriter.writeAsVectorFormat(vlayer, 
                                                         self.outputfile, 
                                                         voptions)

        if result[0] != 0:
            QMessageBox.critical(self,'Map Creator','Error creating shapefile.')
        else: #Ask to add shapfile to map
            name = QFileInfo(self.outputfile).completeBaseName()
            result = QMessageBox.question(self,'Map Creator',
                                          'Add shapefile to map?',
                                          QMessageBox.Yes,
                                          QMessageBox.No)
            if result == QMessageBox.Yes:
                self.iface.addVectorLayer(self.outputfile, name, 'ogr')
                
        self.setCursor(Qt.ArrowCursor)
コード例 #14
0
ファイル: vectorize.py プロジェクト: Riverscapes/RIPTPlugin
def raster_to_polygon(raster_path, out_gpkg, out_layer_name, raster_value, surface_name='valley bottom'):

    # raster_layer = QgsRasterLayer(raster_path, 'in_raster')
    out_polygon_path = os.path.join(out_gpkg, out_layer_name)

    # --------- PROCESSING -------------

    # -- DEM --
    tempdir = tempfile.TemporaryDirectory()
    temp_raster = os.path.join(tempdir.name, "less_than.tif")

    gp_calc = processing.run('gdal:rastercalculator', {'INPUT_A': raster_path,
                                                       'BAND_A': 1,
                                                       'FORMULA': f'(A <= {raster_value})',
                                                       'OUTPUT': temp_raster})  # 'raster'})

    # raster_less_than = gp_calc['OUTPUT']

    raster_less_than = QgsRasterLayer(gp_calc['OUTPUT'])

    # -- DEM to VECTOR --
    gp_raw = processing.run("gdal:polygonize",
                            {'INPUT': raster_less_than,
                             'BAND': 1,
                             'FIELD': 'DN',
                             'EIGHT_CONNECTEDNESS': False,
                             'EXTRA': '',
                             'OUTPUT': 'TEMPORARY_OUTPUT'})

    raw_vector = QgsVectorLayer(
        gp_raw['OUTPUT'], "raw_vectors", "ogr")

    # TODO remove when done
    # QgsProject.instance().addMapLayer(raw_vector)

    # -- CALCULATE AREA --
    # create a provider
    pv = raw_vector.dataProvider()

    # add the attribute and update
    pv.addAttributes([QgsField('raw_area_m', QVariant.Int), QgsField(
        'max_elev_m', QVariant.Double), QgsField('surface_name', QVariant.String)])
    raw_vector.updateFields()

    # Create a context and scope
    context = QgsExpressionContext()
    context.appendScopes(
        QgsExpressionContextUtils.globalProjectLayerScopes(raw_vector))

    # Loop through and add the areas
    delete_features = []
    with edit(raw_vector):
        # loop them
        for feature in raw_vector.getFeatures():
            if feature['DN'] != 1:
                delete_features.append(feature.id())
            else:
                context.setFeature(feature)
                feature['raw_area_m'] = QgsExpression('$area').evaluate(context)
                feature['max_elev_m'] = raster_value
                feature['surface_name'] = surface_name
                raw_vector.updateFeature(feature)
        raw_vector.dataProvider().deleteFeatures(delete_features)

    # -- BUFFER POLYGONS --
    gp_buffered = processing.run("native:buffer",
                                 {'INPUT': raw_vector,
                                  'DISTANCE': 0.000001,
                                  'SEGMENTS': 5,
                                  'END_CAP_STYLE': 0,
                                  'JOIN_STYLE': 0,
                                  'MITER_LIMIT': 2,
                                  'DISSOLVE': False,
                                  'OUTPUT': 'TEMPORARY_OUTPUT'})

    buffered_vector = gp_buffered['OUTPUT']

    # TODO remove when final
    # QgsProject.instance().addMapLayer(buffered_vector)

    # -- Simplify Polygons --
    gp_simple = processing.run("native:simplifygeometries",
                               {'INPUT': buffered_vector,
                                'METHOD': 0,
                                'TOLERANCE': simplify_tolerance,
                                'OUTPUT': 'TEMPORARY_OUTPUT'})

    simple_vector = gp_simple['OUTPUT']  # QgsVectorLayer(
    # gp_simplify['OUTPUT'], "simplified_polygons", 'ogr')

    # -- Smooth the polygons --
    gp_smooth = processing.run("native:smoothgeometry",
                               {'INPUT': simple_vector,
                                'ITERATIONS': 1,
                                'OFFSET': smoothing_offset,
                                'MAX_ANGLE': 180,
                                'OUTPUT': 'TEMPORARY_OUTPUT'})

    smooth_vector = gp_smooth['OUTPUT']  # QgsVectorLayer(
    # , "smoothed_polygons", 'ogr')

    gp_multi = processing.run("native:multiparttosingleparts",
                              {'INPUT': smooth_vector,
                               'OUTPUT': 'TEMPORARY_OUTPUT'})

    multi_vector = gp_multi['OUTPUT']

    # Fix any crossed geometry as final vector
    gp_fix = processing.run("native:fixgeometries",
                            {'INPUT': multi_vector,
                             'OUTPUT': 'TEMPORARY_OUTPUT'})

    final_vector = gp_fix['OUTPUT']

    # Create a context and scope
    # Understand WTF this is??
    context = QgsExpressionContext()
    context.appendScopes(
        QgsExpressionContextUtils.globalProjectLayerScopes(final_vector))

    # add an area attribute
    # create a provider
    pv = final_vector.dataProvider()

    # add the attribute and update
    pv.addAttributes([QgsField('area_m', QVariant.Int)])
    final_vector.updateFields()

    # Loop through and add the areas
    with edit(final_vector):
        # loop them
        for feature in final_vector.getFeatures():
            context.setFeature(feature)
            feature['area_m'] = QgsExpression('$area').evaluate(context)
            final_vector.updateFeature(feature)

    # -- Delete Unneeded Fields --
    pv = final_vector.dataProvider()
    pv.deleteAttributes([1, 2])
    final_vector.updateFields()

    # -- Delete small polygons --
    # data provider capabilities
    caps = final_vector.dataProvider().capabilities()

    # features and empty list of features to delete
    features = final_vector.getFeatures()
    delete_features = []

    # if the layer can have deleted features
    if caps & QgsVectorDataProvider.DeleteFeatures:
        for feature in features:
            if feature['area_m'] <= polygon_min_size:
                delete_features.append(feature.id())
        final_vector.dataProvider().deleteFeatures(delete_features)

    # TODO fix final data export
    options = QgsVectorFileWriter.SaveVectorOptions()
    options.layerName = out_layer_name
    options.driverName = 'GPKG'
    if os.path.exists(out_gpkg):
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    QgsVectorFileWriter.writeAsVectorFormat(
        final_vector, out_gpkg, options)

    # open the output layer
    QgsVectorLayer(out_polygon_path, out_layer_name, 'ogr')
コード例 #15
0
    def sendOutputFile(self, handler):
        format_dict = WFSFormats[self.format]

        # read the GML
        gml_path = join(self.tempdir, '{}.gml'.format(self.filename))
        output_layer = QgsVectorLayer(gml_path, 'qgis_server_wfs_features',
                                      'ogr')

        # Temporary file where to write the output
        temporary = QTemporaryFile(
            join(QDir.tempPath(),
                 'request-WFS-XXXXXX.{}'.format(format_dict['filenameExt'])))
        temporary.open()
        output_file = temporary.fileName()
        temporary.close()

        if output_layer.isValid():
            try:
                # create save options
                options = QgsVectorFileWriter.SaveVectorOptions()
                # driver name
                options.driverName = format_dict['ogrProvider']
                # file encoding
                options.fileEncoding = 'utf-8'

                # coordinate transformation
                if format_dict['forceCRS']:
                    options.ct = QgsCoordinateTransform(
                        output_layer.crs(),
                        QgsCoordinateReferenceSystem(format_dict['forceCRS']),
                        QgsProject.instance())

                # datasource options
                if format_dict['ogrDatasourceOptions']:
                    options.datasourceOptions = format_dict[
                        'ogrDatasourceOptions']

                # write file
                if Qgis.QGIS_VERSION_INT >= 31003:
                    write_result, error_message = QgsVectorFileWriter.writeAsVectorFormatV2(
                        output_layer, output_file,
                        QgsProject.instance().transformContext(), options)
                else:
                    write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
                        output_layer, output_file, options)

                if write_result != QgsVectorFileWriter.NoError:
                    handler.appendBody(b'')
                    self.logger.critical(error_message)
                    return False

            except Exception as e:
                handler.appendBody(b'')
                self.logger.critical(str(e))
                return False

            if format_dict['zip']:
                # compress files
                import zipfile
                # noinspection PyBroadException
                try:
                    import zlib  # NOQA
                    compression = zipfile.ZIP_DEFLATED
                except Exception:
                    compression = zipfile.ZIP_STORED

                # create the zip file
                zip_file_path = join(self.tempdir, '%s.zip' % self.filename)
                with zipfile.ZipFile(zip_file_path, 'w') as zf:
                    # add all files
                    zf.write(join(
                        self.tempdir,
                        '%s.%s' % (self.filename, format_dict['filenameExt'])),
                             compress_type=compression,
                             arcname='%s.%s' %
                             (self.typename, format_dict['filenameExt']))

                    for e in format_dict['extToZip']:
                        file_path = join(self.tempdir,
                                         '%s.%s' % (self.filename, e))
                        if exists(file_path):
                            zf.write(file_path,
                                     compress_type=compression,
                                     arcname='%s.%s' % (self.typename, e))

                    zf.close()

                f = QFile(zip_file_path)
                if f.open(QFile.ReadOnly):
                    ba = f.readAll()
                    handler.appendBody(ba)
                    return True

            else:
                # return the file created without zip
                f = QFile(output_file)
                if f.open(QFile.ReadOnly):
                    ba = f.readAll()
                    handler.appendBody(ba)
                    return True

        handler.appendBody(b'')
        self.logger.critical('Error no output file')
        return False
コード例 #16
0
def exportLayer(layer,
                fields=None,
                to_shapefile=False,
                path=None,
                force=False,
                logger=None):
    logger = logger or feedback
    filepath, _, ext = lyr_utils.getLayerSourceInfo(layer)
    lyr_name, safe_name = lyr_utils.getLayerTitleAndName(layer)
    fields = fields or []
    if layer.type() == layer.VectorLayer:
        if to_shapefile and (force or layer.fields().count() != len(fields)
                             or ext != EXT_SHAPEFILE):
            # Export with Shapefile extension
            ext = EXT_SHAPEFILE
        elif force or ext != EXT_GEOPACKAGE or layer.fields().count() != len(fields) \
                or not isSingleTableGpkg(filepath):
            # Export with GeoPackage extension
            ext = EXT_GEOPACKAGE
        else:
            # No need to export
            logger.logInfo(
                f"No need to export layer {lyr_name} stored at {filepath}")
            return filepath

        # Perform GeoPackage or Shapefile export
        attrs = [
            i for i, f in enumerate(layer.fields())
            if len(fields) == 0 or f.name() in fields
        ]
        output = path or tempFileInSubFolder(safe_name + ext)
        encoding = "UTF-8"
        driver = "ESRI Shapefile" if ext == EXT_SHAPEFILE else "GPKG"
        options = None
        if hasattr(QgsVectorFileWriter, 'SaveVectorOptions'):
            # QGIS v3.x has the SaveVectorOptions object
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.fileEncoding = encoding
            options.attributes = attrs
            options.driverName = driver
        # Make sure that we are using the latest (non-deprecated) write method
        if hasattr(QgsVectorFileWriter, 'writeAsVectorFormatV3'):
            # Use writeAsVectorFormatV3 for QGIS versions >= 3.20 to avoid DeprecationWarnings
            result = QgsVectorFileWriter.writeAsVectorFormatV3(
                layer, output, QgsCoordinateTransformContext(),
                options)  # noqa
        elif hasattr(QgsVectorFileWriter, 'writeAsVectorFormatV2'):
            # Use writeAsVectorFormatV2 for QGIS versions >= 3.10.3 to avoid DeprecationWarnings
            result = QgsVectorFileWriter.writeAsVectorFormatV2(
                layer, output, QgsCoordinateTransformContext(),
                options)  # noqa
        else:
            # Use writeAsVectorFormat for QGIS versions < 3.10.3 for backwards compatibility
            result = QgsVectorFileWriter.writeAsVectorFormat(
                layer,
                output,
                fileEncoding=encoding,
                attributes=attrs,
                driverName=driver)  # noqa
        # Check if first item in result tuple is an error code
        if result[0] == QgsVectorFileWriter.NoError:
            logger.logInfo(f"Layer {lyr_name} exported to {output}")
        else:
            # Dump the result tuple as-is when there are errors (the tuple size depends on the QGIS version)
            logger.logError(
                f"Layer {lyr_name} failed to export.\n\tResult object: {str(result)}"
            )
        return output
    else:
        # Export raster
        if force or not filepath.lower().endswith("tif"):
            output = path or tempFileInSubFolder(safe_name + ".tif")
            writer = QgsRasterFileWriter(output)
            writer.setOutputFormat("GTiff")
            writer.writeRaster(layer.pipe(), layer.width(), layer.height(),
                               layer.extent(), layer.crs())
            del writer
            logger.logInfo(f"Layer {lyr_name} exported to {output}")
            return output
        else:
            logger.logInfo(
                f"No need to export layer {lyr_name} stored at {filepath}")
            return filepath
コード例 #17
0
    def sendOutputFile(self, handler):
        formatDict = WFSFormats[self.format]
        # read the GML
        outputLayer = QgsVectorLayer(
            os.path.join(self.tempdir, '%s.gml' % self.filename),
            'qgis_server_wfs_features', 'ogr')
        if outputLayer.isValid():
            try:
                # create save options
                options = QgsVectorFileWriter.SaveVectorOptions()
                # driver name
                options.driverName = formatDict['ogrProvider']
                # file encoding
                options.fileEncoding = 'utf-8'
                # coordinate transformation
                if formatDict['forceCRS']:
                    options.ct = QgsCoordinateTransform(
                        outputLayer.crs(),
                        QgsCoordinateReferenceSystem(formatDict['forceCRS']),
                        QgsProject.instance())
                # datasource options
                if formatDict['ogrDatasourceOptions']:
                    options.datasourceOptions = formatDict[
                        'ogrDatasourceOptions']

                # write file
                write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
                    outputLayer,
                    os.path.join(
                        self.tempdir,
                        '%s.%s' % (self.filename, formatDict['filenameExt'])),
                    options)
                if write_result != QgsVectorFileWriter.NoError:
                    handler.appendBody(b'')
                    QgsMessageLog.logMessage(error_message,
                                             "wfsOutputExtension",
                                             Qgis.Critical)
                    return False
            except Exception as e:
                handler.appendBody(b'')
                QgsMessageLog.logMessage(str(e), "wfsOutputExtension",
                                         Qgis.Critical)
                return False

            if formatDict['zip']:
                # compress files
                import zipfile
                try:
                    import zlib
                    compression = zipfile.ZIP_DEFLATED
                except:
                    compression = zipfile.ZIP_STORED
                # create the zip file
                with zipfile.ZipFile(
                        os.path.join(self.tempdir, '%s.zip' % self.filename),
                        'w') as zf:
                    # add all files
                    zf.write(os.path.join(
                        self.tempdir,
                        '%s.%s' % (self.filename, formatDict['filenameExt'])),
                             compress_type=compression,
                             arcname='%s.%s' %
                             (self.typename, formatDict['filenameExt']))
                    for e in formatDict['extToZip']:
                        if os.path.exists(
                                os.path.join(self.tempdir,
                                             '%s.%s' % (self.filename, e))):
                            zf.write(os.path.join(self.tempdir, '%s.%s' %
                                                  (self.filename, e)),
                                     compress_type=compression,
                                     arcname='%s.%s' % (self.typename, e))
                    zf.close()
                f = QFile(os.path.join(self.tempdir, '%s.zip' % self.filename))
                if (f.open(QFile.ReadOnly)):
                    ba = f.readAll()
                    handler.appendBody(ba)
                    return True
            else:
                # return the file created without zip
                f = QFile(
                    os.path.join(
                        self.tempdir,
                        '%s.%s' % (self.filename, formatDict['filenameExt'])))
                if (f.open(QFile.ReadOnly)):
                    ba = f.readAll()
                    handler.appendBody(ba)
                    return True

        handler.appendBody(b'')
        QgsMessageLog.logMessage('Error no output file', "wfsOutputExtension",
                                 Qgis.Critical)
        return False
コード例 #18
0
    def run(self):
        for dlIndex in range(0, self.total_download_count):
            url = self.all_urls[dlIndex][0]
            url_parts = url.split('/')
            file_name = url_parts[-1].split('?')[0]
            data_dir_name = self.all_urls[dlIndex][1]
            data_dir_name = data_dir_name.replace(":", "_suhde_")
            dir_path = os.path.join(self.data_download_dir, data_dir_name)
            dir_path = os.path.join(dir_path, file_name.split('.')[0])
            data_type = self.all_urls[dlIndex][3]

            percentage = dlIndex / float(self.total_download_count) * 100.0
            self.setProgress(percentage)

            if not os.path.exists(dir_path):
                QgsMessageLog.logMessage("Skipping directory: " + dir_path,
                                         'NLSgpkgloader', 1)
                continue

            for listed_file_name in os.listdir(dir_path):
                if data_type == "gml" and listed_file_name.endswith(".xml"):
                    driver = ogr.GetDriverByName('GML')
                    data_source = driver.Open(
                        os.path.join(dir_path, listed_file_name), 0)
                    layer_count = data_source.GetLayerCount()
                    mtk_layer_count = 0  # Used for breaking from the for loop when all MTK layers chosen by the user have been added
                    for i in range(layer_count):
                        if self.isCanceled():
                            return False
                        layer = data_source.GetLayerByIndex(i)
                        layer_name = layer.GetName()
                        if layer_name in self.products:
                            new_layer = QgsVectorLayer(
                                os.path.join(dir_path, listed_file_name) +
                                "|layerid=" + str(i), layer_name, "ogr")
                            if new_layer.isValid():
                                options = QgsVectorFileWriter.SaveVectorOptions(
                                )
                                options.layerName = layer_name
                                options.driverName = "GPKG"
                                options.fileEncoding = "UTF-8"
                                if os.path.isfile(self.gpkg_path):
                                    if QgsVectorLayer(self.gpkg_path +
                                                      "|layername=" +
                                                      layer_name).isValid():
                                        options.actionOnExistingFile = QgsVectorFileWriter.AppendToLayerNoNewFields
                                    else:
                                        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
                                else:
                                    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
                                e = QgsVectorFileWriter.writeAsVectorFormat(
                                    new_layer, self.gpkg_path, options)
                                if e[0]:
                                    QgsMessageLog.logMessage(
                                        "Failed to write layer " + layer_name +
                                        " to geopackage", 'NLSgpkgloader', 2)
                                    break
                                mtk_layer_count += 1
                            else:
                                # TODO: handle invalid layer error
                                #QgsMessageLog.logMessage("Invalid layer: " + listed_file_name + ":" layer_name, 'NLSgpkgloader', 2)
                                pass

                        if mtk_layer_count == len(self.products):
                            break
                else:
                    QgsMessageLog.logMessage(
                        "cannot add the data type " + data_type +
                        ", listed_file_name: " + listed_file_name,
                        'NLSgpkgloader', 0)
        return True
コード例 #19
0
        def _test(autoTransaction):
            """Test buffer methods within and without transactions

            - create a feature
            - save
            - retrieve the feature
            - change geom and attrs
            - test changes are seen in the buffer
            """
            def _check_feature(wkt):

                f = next(layer_a.getFeatures())
                self.assertEqual(f.geometry().asWkt().upper(), wkt)
                f = list(buffer.addedFeatures().values())[0]
                self.assertEqual(f.geometry().asWkt().upper(), wkt)

            ml = QgsVectorLayer(
                'Point?crs=epsg:4326&field=int:integer&field=int2:integer',
                'test', 'memory')
            self.assertTrue(ml.isValid())

            d = QTemporaryDir()
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.driverName = 'GPKG'
            options.layerName = 'layer_a'
            err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
                ml, os.path.join(d.path(), 'transaction_test.gpkg'),
                QgsCoordinateTransformContext(), options)

            self.assertEqual(err, QgsVectorFileWriter.NoError)
            self.assertTrue(os.path.isfile(newFileName))

            layer_a = QgsVectorLayer(newFileName + '|layername=layer_a')

            self.assertTrue(layer_a.isValid())

            project = QgsProject()
            project.setAutoTransaction(autoTransaction)
            project.addMapLayers([layer_a])

            ###########################################
            # Tests with a new feature

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 123)
            f.setGeometry(QgsGeometry.fromWkt('point(7 45)'))
            self.assertTrue(layer_a.addFeatures([f]))

            _check_feature('POINT (7 45)')

            # Need to fetch the feature because its ID is NULL (-9223372036854775808)
            f = next(layer_a.getFeatures())

            self.assertEqual(len(buffer.addedFeatures()), 1)
            layer_a.undoStack().undo()
            self.assertEqual(len(buffer.addedFeatures()), 0)
            layer_a.undoStack().redo()
            self.assertEqual(len(buffer.addedFeatures()), 1)
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)

            # Now change attribute
            self.assertEqual(buffer.changedAttributeValues(), {})
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValue(f.id(), 1, 321)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])

            self.assertEqual(len(buffer.addedFeatures()), 1)
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 321)

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123])
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)

            # Change multiple attributes
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValues(f.id(), {1: 321, 2: 456})
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])
            self.assertEqual(spy_attribute_changed[1], [f.id(), 2, 456])
            buffer = layer_a.editBuffer()
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            # This is because QgsVectorLayerUndoCommandChangeAttribute plural
            if not autoTransaction:
                layer_a.undoStack().undo()
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.attribute('int2'), None)
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(
                spy_attribute_changed[1 if autoTransaction else 0],
                [f.id(), 2, None])
            self.assertEqual(
                spy_attribute_changed[0 if autoTransaction else 1],
                [f.id(), 1, 123])

            # Change geometry
            f = next(layer_a.getFeatures())
            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            self.assertTrue(len(spy_geometry_changed), 1)
            self.assertEqual(spy_geometry_changed[0][0], f.id())
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(9 43)').asWkt())

            _check_feature('POINT (9 43)')
            self.assertEqual(buffer.changedGeometries(), {})

            layer_a.undoStack().undo()

            _check_feature('POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            _check_feature('POINT (9 43)')

            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(10 44)')))
            _check_feature('POINT (10 44)')

            # This is another surprise: geometry edits get collapsed into a single
            # one because they have the same hardcoded id
            layer_a.undoStack().undo()
            _check_feature('POINT (7 45)')

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Tests with the existing feature

            # Get the feature
            f = next(layer_a.getFeatures())
            self.assertTrue(f.isValid())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')

            # Change single attribute
            self.assertTrue(layer_a.startEditing())
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValue(f.id(), 1, 321)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])
            buffer = layer_a.editBuffer()
            self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}})

            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute(1), 321)

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute(1), 123)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123])
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change attributes
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValues(f.id(), {1: 111, 2: 654})
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(spy_attribute_changed[0], [1, 1, 111])
            self.assertEqual(spy_attribute_changed[1], [1, 2, 654])
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attributes(), [1, 111, 654])
            self.assertEqual(buffer.changedAttributeValues(),
                             {1: {
                                 1: 111,
                                 2: 654
                             }})

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            # This is because QgsVectorLayerUndoCommandChangeAttribute plural
            if not autoTransaction:
                layer_a.undoStack().undo()
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(
                spy_attribute_changed[0 if autoTransaction else 1],
                [1, 1, 123])
            self.assertEqual(
                spy_attribute_changed[1 if autoTransaction else 0],
                [1, 2, None])
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attributes(), [1, 123, None])
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change geometry
            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            self.assertEqual(spy_geometry_changed[0][0], 1)
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(9 43)').asWkt())

            f = next(layer_a.getFeatures())
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)')
            self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(),
                             'POINT (9 43)')

            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            layer_a.undoStack().undo()
            self.assertEqual(spy_geometry_changed[0][0], 1)
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(7 45)').asWkt())
            self.assertEqual(buffer.changedGeometries(), {})
            f = next(layer_a.getFeatures())

            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            # Delete an existing feature
            self.assertTrue(layer_a.deleteFeature(f.id()))
            with self.assertRaises(StopIteration):
                next(layer_a.getFeatures())
            self.assertEqual(buffer.deletedFeatureIds(), [f.id()])

            layer_a.undoStack().undo()
            self.assertTrue(layer_a.getFeature(f.id()).isValid())
            self.assertEqual(buffer.deletedFeatureIds(), [])

            ###########################################
            # Test delete

            # Delete a new feature
            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 555)
            f.setGeometry(QgsGeometry.fromWkt('point(8 46)'))
            self.assertTrue(layer_a.addFeatures([f]))
            f = [
                f for f in layer_a.getFeatures() if f.attribute('int') == 555
            ][0]
            self.assertTrue(f.id() in buffer.addedFeatures())
            self.assertTrue(layer_a.deleteFeature(f.id()))
            self.assertFalse(f.id() in buffer.addedFeatures())
            self.assertFalse(f.id() in buffer.deletedFeatureIds())

            layer_a.undoStack().undo()
            self.assertTrue(f.id() in buffer.addedFeatures())

            ###########################################
            # Add attribute

            field = QgsField('attr1', QVariant.String)
            self.assertTrue(layer_a.addAttribute(field))
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [])

            layer_a.undoStack().redo()
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Remove attribute

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertTrue(layer_a.deleteAttribute(attr_idx))
            self.assertEqual(buffer.deletedAttributeIds(), [attr_idx])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.deletedAttributeIds(), [])
            self.assertEqual(layer_a.fields().lookupField(field.name()),
                             attr_idx)

            # This is totally broken at least on OGR/GPKG: the rollback
            # does not restore the original fields
            if False:

                layer_a.undoStack().redo()
                self.assertEqual(buffer.deletedAttributeIds(), [attr_idx])
                self.assertEqual(layer_a.fields().lookupField(field.name()),
                                 -1)

                # Rollback!
                self.assertTrue(layer_a.rollBack())

                self.assertIn('attr1', layer_a.dataProvider().fields().names())
                self.assertIn('attr1', layer_a.fields().names())
                self.assertEqual(layer_a.fields().names(),
                                 layer_a.dataProvider().fields().names())

                attr_idx = layer_a.fields().lookupField(field.name())
                self.assertNotEqual(attr_idx, -1)

                self.assertTrue(layer_a.startEditing())
                attr_idx = layer_a.fields().lookupField(field.name())
                self.assertNotEqual(attr_idx, -1)

            ###########################################
            # Rename attribute

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)
            self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name'))
            self.assertEqual(layer_a.fields().lookupField('new_name'),
                             attr_idx)

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()),
                             attr_idx)
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)

            layer_a.undoStack().redo()
            self.assertEqual(layer_a.fields().lookupField('new_name'),
                             attr_idx)
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            #############################################
            # Try hard to make this fail for transactions
            if autoTransaction:
                self.assertTrue(layer_a.commitChanges())
                self.assertTrue(layer_a.startEditing())
                f = next(layer_a.getFeatures())

                # Do
                for i in range(10):
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.changeAttributeValue(f.id(), 2, i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0], [f.id(), 2, i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: i
                                      }})
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), i)

                # Undo/redo
                for i in range(9):

                    # Undo
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().undo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 8 - i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: 8 - i
                                      }})

                    # Redo
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().redo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 9 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 9 - i])

                    # Undo again
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().undo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 8 - i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: 8 - i
                                      }})

                    # Last check
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)

                self.assertEqual(buffer.changedAttributeValues(),
                                 {f.id(): {
                                      2: 0
                                  }})
                layer_a.undoStack().undo()
                buffer = layer_a.editBuffer()
                self.assertEqual(buffer.changedAttributeValues(), {})
                f = next(layer_a.getFeatures())
                self.assertEqual(f.attribute(2), None)
コード例 #20
0
    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
        if self.first_start == True:
            self.first_start = False
            self.dlg = TransferLayerFileGdbToGeoPackageDialog()
            self.dlg.pushButton.clicked.connect(self.select_output_file)

        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed

        if result:
            # Faire une lsite de ce que contient la geobase
            list = fiona.listlayers(self.dlg.lineEdit.text())
            tmp = self.dlg.lineEdit.text()
            filename = tmp.replace(".gdb", "")
            gdb = filename + '.gdb'

            # progressMessageBar = self.iface.messageBar().createMessage("Doing something boring...")
            # progress = self.QProgressBar()

            for name in list:

                try:
                    name2 = (name.replace('_', ''))
                    ce = '{0}'.format(gdb) + '|' + 'layername=' + '{0}'.format(
                        name)

                    # faire un layer avec la string
                    layer = QgsVectorLayer(ce, '{0}'.format(name), 'ogr')

                    if path.isfile(filename + '.gpkg'):

                        options = QgsVectorFileWriter.SaveVectorOptions()
                        # permet de copier plusieurs classe d'entité et table
                        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer

                        options.driverName = 'GPKG'
                        options.layerName = '{0}'.format(name2)
                        QgsVectorFileWriter.writeAsVectorFormat(
                            layer, filename, options)

                    else:
                        options = QgsVectorFileWriter.SaveVectorOptions()
                        options.driverName = 'GPKG'
                        # options.layerName = '{0}'.format(name2)
                        QgsVectorFileWriter.writeAsVectorFormat(
                            layer, filename, options)

                except Exception as e:
                    continue

            self.iface.messageBar().pushMessage("Réussi ! ",
                                                "Le GeoPackage est situé :  " +
                                                filename + '.gpkg',
                                                level=Qgis.Success,
                                                duration=10)

            pass
コード例 #21
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        source = self.parameterAsSource(parameters, self.INPUT, context)
        path = self.parameterAsFile(parameters, self.OUTPUT, context)

        field_def = {
            'idx': QVariant.Int,
            'name': QVariant.String,
            'type': QVariant.Int,
            'typeName': QVariant.String,
            'length': QVariant.Int,
            'precision': QVariant.Int,
            'comment': QVariant.String,
            'alias': QVariant.String
        }

        # create virtual layer
        vl = QgsVectorLayer("None", "fields", "memory")
        pr = vl.dataProvider()

        # define fields
        fields = QgsFields()
        for n, t in field_def.items():
            fields.append(QgsField(name=n, type=t))

        # add fields
        pr.addAttributes(fields)
        vl.updateFields(
        )  # tell the vector layer to fetch changes from the provider

        # add feature based on field description
        field_index = 0
        for f in providerFields(source.fields()):
            field_index += 1
            feat = QgsFeature()
            feat.setAttributes([
                field_index,
                f.name(),
                f.type(),
                f.typeName(),
                f.length(),
                f.precision(),
                f.comment(),
                f.alias()
            ])
            pr.addFeatures([feat])

        # set create file layer options
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = QgsVectorFileWriter.driverForExtension('csv')
        options.fileEncoding = 'UTF-8'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
        options.layerOptions = ['CREATE_CSVT=YES']

        # write file
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            vl, path, options)

        # result
        if write_result != QgsVectorFileWriter.NoError:
            raise QgsProcessingException(
                self.tr('* ERROR: {0}').format(error_message))

        del fields
        del pr
        del vl

        # create layer
        dest_layer = QgsVectorLayer(path, self.OUTPUT_LAYER, 'ogr')
        if not dest_layer.isValid():
            raise QgsProcessingException(
                self.tr('* ERROR: Can\'t load layer {1} in {0}').format(
                    path, self.OUTPUT_LAYER))

        # Add layer to context
        context.temporaryLayerStore().addMapLayer(dest_layer)
        context.addLayerToLoadOnCompletion(
            dest_layer.id(),
            QgsProcessingContext.LayerDetails(self.OUTPUT_LAYER,
                                              context.project(),
                                              self.OUTPUT_LAYER))

        return {self.OUTPUT: path, self.OUTPUT_LAYER: dest_layer.id()}
コード例 #22
0
    def create_zensus_rings(self):
        '''
        intersect study area with zensus raster
        '''
        self.log('Extrahiere Siedlungszellen aus Zensusdaten...')
        epsg = self.project.settings.EPSG
        zensus_file = os.path.join(self.project.basedata.base_path,
                                   self.project.settings.ZENSUS_100_FILE)

        bbox = get_bbox(self.gemeinden.table)
        clipped_raster, raster_epsg = clip_raster(zensus_file, bbox)

        raster_layer = QgsRasterLayer(clipped_raster)

        parameters = {
            'INPUT_RASTER': raster_layer,
            'RASTER_BAND': 1,
            'FIELD_NAME': 'ew',
            'OUTPUT': 'memory:'
        }

        point_layer = processing.run('native:pixelstopoints',
                                     parameters)['OUTPUT']
        point_layer.setSubsetString('ew>0')

        parameters = {
            'INPUT': point_layer,
            'TARGET_CRS': f'EPSG:{epsg}',
            'OUTPUT': 'memory:'
        }

        point_proj = processing.run('native:reprojectlayer',
                                    parameters)['OUTPUT']

        # clip with max distance from project area
        buffer_geom = self.project_frame.geom.buffer(self.rings[-1], 100)
        buffer = QgsFeature()
        buffer.setGeometry(buffer_geom)
        overlay = QgsVectorLayer(f'Polygon?crs=EPSG:{epsg}', 'buffer',
                                 'memory')
        overlay.dataProvider().addFeature(buffer)
        parameters = {
            'INPUT': point_proj,
            'OVERLAY': overlay,
            'OUTPUT': 'memory:'
        }
        clipped_layer = processing.run('native:clip', parameters)['OUTPUT']

        # intersect with rings to get distance bin
        ring_layer = QgsVectorLayer(f'Polygon?crs=EPSG:{epsg}', 'rings',
                                    'memory')
        pr = ring_layer.dataProvider()
        pr.addAttributes([QgsField('ring', QVariant.Int)])
        ring_layer.updateFields()
        prev_outer_circle = None
        for distance in self.rings:
            ring = QgsFeature()
            outer_circle = self.project_frame.geom.buffer(distance, 100)
            if prev_outer_circle is not None:
                geom = outer_circle.difference(prev_outer_circle)
            else:
                geom = outer_circle
            prev_outer_circle = outer_circle
            ring.setGeometry(geom)
            ring.setAttributes([distance])
            pr.addFeature(ring)

        self.log('Verschneide Siedlungszellen mit Entfernungsringen '
                 'und Gemeinden...')
        parameters = {
            'INPUT': clipped_layer,
            'OVERLAY': ring_layer,
            'OUTPUT': 'memory:'
        }
        clipped_w_distance = processing.run('native:intersection',
                                            parameters)['OUTPUT']

        # intersect with "gemeinden" to add AGS to cells
        gem_overlay = create_layer(self.gemeinden,
                                   'Polygon',
                                   fields=['AGS'],
                                   name='overlay',
                                   epsg=epsg)
        parameters = {
            'INPUT': clipped_w_distance,
            'OVERLAY': gem_overlay,
            'OUTPUT': 'memory:'
        }
        clipped_w_ags = processing.run('native:intersection',
                                       parameters)['OUTPUT']

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.actionOnExistingFile = \
            QgsVectorFileWriter.CreateOrOverwriteLayer
        options.layerName = 'zensus_rings'
        QgsVectorFileWriter.writeAsVectorFormat(clipped_w_ags,
                                                self.gemeinden.workspace.path,
                                                options)

        return clipped_w_ags
コード例 #23
0
ファイル: agtools.py プロジェクト: yoichigmf/QGIS_stat
def SplitMesh(outputdb, meshtable, output_table, SplitFlag, keycolum,
              divcolumn):

    mlayer = meshtable

    if type(meshtable) is str:

        #    入力メッシュレイヤ
        dmesh = outputdb + "|layername=" + meshtable

        mlayer = QgsVectorLayer(dmesh, "mesh", "ogr")

    if mlayer.isValid():
        print("dmesh Layer load OK")
    else:
        print("dmesh Layer load Fail")
        print("dmesh=" + meshtable)
        sys.exit()

    out_tb = outputdb + "|layername=" + output_table

    crsstr = mlayer.crs().authid()

    #   作業結果出力レイヤ

    vectL = 'Polygon?crs=' + crsstr

    vl1 = QgsVectorLayer(vectL, "temporary_mesh", "memory")

    if not vl1:
        print("Virtual Layer failed to load!")
        sys.exit()
    else:
        print(out_tb)

    #vl1.setCrs( mlayer.crs()  )

    pr1 = vl1.dataProvider()

    #  フィールド定義
    pr1.addAttributes([
        QgsField(keycolum, QVariant.String),
        QgsField(divcolumn, QVariant.Int)
    ])

    vl1.updateFields()  #

    vl1.beginEditCommand("Add Polygons")

    features = mlayer.getFeatures()

    for feature in features:

        code = feature[keycolum]
        divide_f = feature[divcolumn]

        #print( 'code =' + code+ ' divide=' + str(divide_f) )
        geom = feature.geometry()
        geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType())

        if divide_f == 0:

            if geom.type() == QgsWkbTypes.PolygonGeometry:

                if geomSingleType:
                    x = geom.asPolygon()

                    #print("Polygon: ", x, "Area: ", geom.area())

                    for xp in x:
                        #print("xp:",xp )

                        #for xxp in xp:
                        #     print("xxp:",xxp)

                        #    座標の場所を判定して位置関係を正規化したほうがいいかも
                        #

                        p0_1 = GetCyuuten(xp[0], xp[1])
                        p1_2 = GetCyuuten(xp[1], xp[2])
                        p2_3 = GetCyuuten(xp[2], xp[3])
                        p3_4 = GetCyuuten(xp[3], xp[4])
                        pC_C = GetCyuuten(p0_1, p2_3)

                        #    新しいキーコード
                        ncode1 = code + '-01'

                        Polygon1 = QgsGeometry.fromPolygonXY([[
                            QgsPointXY(xp[0].x(), xp[0].y()),
                            QgsPointXY(p0_1.x(), p0_1.y()),
                            QgsPointXY(pC_C.x(), pC_C.y()),
                            QgsPointXY(p3_4.x(), p3_4.y())
                        ]])

                        # add a feature
                        fet = QgsFeature(pr1.fields())

                        fet.setGeometry(Polygon1)

                        fet[keycolum] = ncode1
                        fet[divcolumn] = divide_f
                        #  新しい feature を作って別レイヤに格納する
                        retc = pr1.addFeatures([fet])

                        #print("add new")
                        #print( retc )

                        #    新しいキーコード
                        ncode2 = code + '-02'
                        Polygon2 = QgsGeometry.fromPolygonXY([[
                            QgsPointXY(p0_1.x(), p0_1.y()),
                            QgsPointXY(xp[1].x(), xp[1].y()),
                            QgsPointXY(p1_2.x(), p1_2.y()),
                            QgsPointXY(pC_C.x(), pC_C.y())
                        ]])

                        fet2 = QgsFeature(pr1.fields())

                        fet2.setGeometry(Polygon2)

                        fet2[keycolum] = ncode2
                        fet2[divcolumn] = divide_f
                        #  新しい feature を作って別レイヤに格納する
                        retc = pr1.addFeatures([fet2])

                        #    新しいキーコード
                        ncode3 = code + '-03'
                        Polygon3 = QgsGeometry.fromPolygonXY([[
                            QgsPointXY(pC_C.x(), pC_C.y()),
                            QgsPointXY(p1_2.x(), p1_2.y()),
                            QgsPointXY(xp[2].x(), xp[2].y()),
                            QgsPointXY(p2_3.x(), p2_3.y())
                        ]])

                        fet3 = QgsFeature(pr1.fields())

                        fet3.setGeometry(Polygon3)

                        fet3[keycolum] = ncode3
                        fet3[divcolumn] = divide_f
                        #  新しい feature を作って別レイヤに格納する
                        retc = pr1.addFeatures([fet3])

                        #    新しいキーコード
                        ncode4 = code + '-04'
                        Polygon4 = QgsGeometry.fromPolygonXY([[
                            QgsPointXY(p3_4.x(), p3_4.y()),
                            QgsPointXY(pC_C.x(), pC_C.y()),
                            QgsPointXY(p2_3.x(), p2_3.y()),
                            QgsPointXY(xp[3].x(), xp[3].y())
                        ]])

                        fet4 = QgsFeature(pr1.fields())

                        fet4.setGeometry(Polygon4)

                        fet4[keycolum] = ncode4
                        fet4[divcolumn] = divide_f
                        #  新しい feature を作って別レイヤに格納する
                        retc = pr1.addFeatures([fet4])

                    #print(Polygon1)
                    # print(Polygon2)

                    #Poly

                    #feat.setGeometry( QgsGeometry.fromPolygonXY([QgsPointXY(546016, 4760165), p2, p3]))
                    #qPolygon1 = QgsGeometry.fromPolygonXY([ xp[0],p0_1, pC_C,xp[0]])

                    #print( qPolygon1 )

                #   一点目 2点目の中点を求める   2

                else:
                    x = geom.asMultiPolygon()
                #print("MultiPolygon: ", x, "Area: ", geom.area())
            else:
                print("geometry is not polygon!")

        else:  #  分割不要ポリゴンはそのまま書き込む
            retc = pr1.addFeatures([feature])

    vl1.updateExtents()
    vl1.endEditCommand()
    vl1.commitChanges()

    features2 = vl1.getFeatures()

    print("-------------------------- vl1 features ------------------------")
    #for feature2 in features2:

    #          print( feature2 )

    options = QgsVectorFileWriter.SaveVectorOptions()
    options.driverName = 'GPKG'
    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    options.layerName = output_table

    #print( "outputdb ==>"+outputdb )
    #print( "output ==>"+output_table )

    #  結果レイヤ書き込み
    write_result, error = QgsVectorFileWriter.writeAsVectorFormat(
        vl1, outputdb, options)
    #if error == QgsVectorFileWriter.NoError:
    #         print("success again!")

    #print( error )
    #print( write_result )

    return (output_table)
コード例 #24
0
    def __init__(self, iface: QgisInterface, version: str, plugin_dir: str, isBatch: bool, isHUC: bool=False, logFile: Optional[str]=None) -> None:
        """Initialise class variables."""
        settings = QSettings()
        if settings.contains('/QSWATPlus/SWATPlusDir'):
            SWATPlusDir = settings.value('/QSWATPlus/SWATPlusDir')
            if not os.path.isdir(SWATPlusDir):
                SWATPlusDir = Parameters._SWATPLUSDEFAULTDIR 
        else:
            SWATPlusDir = Parameters._SWATPLUSDEFAULTDIR
        if not os.path.isdir(SWATPlusDir):
            QSWATUtils.error('''Cannot find SWATPlus directory, expected to be {0}.
Please use the Parameters form to set its location.'''.format(SWATPlusDir), isBatch)
        else:
            settings.setValue('/QSWATPlus/SWATPlusDir', SWATPlusDir)
        ## SWATPlus directory
        self.SWATPlusDir = SWATPlusDir
        ## Directory containing QSWAT plugin
        self.plugin_dir = plugin_dir
        ## Databases directory: part of plugin
        # containing template project and reference databases, plus soil database for STATSGO and SSURGO
        self.dbPath = QSWATUtils.join(self.SWATPlusDir, Parameters._DBDIR)
        ## Path of template project database
        self.dbProjTemplate =  QSWATUtils.join(self.dbPath, Parameters._DBPROJ)
        ## Path of template reference database
        self.dbRefTemplate = QSWATUtils.join(self.dbPath, Parameters._DBREF)
        ## Directory of TauDEM executables
        self.TauDEMDir = TauDEMUtils.findTauDEMDir(settings, not isBatch)[0]
        ## Path of mpiexec
        self.mpiexecPath = TauDEMUtils.findMPIExecPath(settings)
        proj: QgsProject = QgsProject.instance()
        title = proj.title()
        ## QGIS interface
        self.iface = iface
        ## project projection (set from DEM)
        self.crsProject: Optional[QgsCoordinateReferenceSystem] = None
        ## Stream burn-in depth
        self.burninDepth: int = proj.readNumEntry(title, 'params/burninDepth', Parameters._BURNINDEPTH)[0]
        ## Channel width multiplier
        self.channelWidthMultiplier: float = proj.readDoubleEntry(title, 'params/channelWidthMultiplier', Parameters._CHANNELWIDTHMULTIPLIER)[0]
        ## Channel width exponent
        self.channelWidthExponent: float = proj.readDoubleEntry(title, 'params/channelWidthExponent', Parameters._CHANNELWIDTHEXPONENT)[0]
        ## Channel depth multiplier
        self.channelDepthMultiplier: float = proj.readDoubleEntry(title, 'params/channelDepthMultiplier', Parameters._CHANNELDEPTHMULTIPLIER)[0]
        ## Channel depth exponent
        self.channelDepthExponent: float = proj.readDoubleEntry(title, 'params/channelDepthExponent', Parameters._CHANNELDEPTHEXPONENT)[0]
        ## reach slope multiplier
        self.reachSlopeMultiplier: float = proj.readDoubleEntry(title, 'params/reachSlopeMultiplier', Parameters._MULTIPLIER)[0]
        ## tributary slope multiplier
        self.tributarySlopeMultiplier: float = proj.readDoubleEntry(title, 'params/tributarySlopeMultiplier', Parameters._MULTIPLIER)[0]
        ## mean slope multiplier
        self.meanSlopeMultiplier: float = proj.readDoubleEntry(title, 'params/meanSlopeMultiplier', Parameters._MULTIPLIER)[0]
        ## main length multiplier
        self.mainLengthMultiplier: float = proj.readDoubleEntry(title, 'params/mainLengthMultiplier', Parameters._MULTIPLIER)[0]
        ## tributary length multiplier
        self.tributaryLengthMultiplier: float = proj.readDoubleEntry(title, 'params/tributaryLengthMultiplier', Parameters._MULTIPLIER)[0]
        ## upslope HRU drain percent
        self.upslopeHRUDrain: int = proj.readNumEntry(title, 'params/upslopeHRUDrain', Parameters._UPSLOPEHRUDRAIN)[0]
        ## Index of slope group in Layers panel
        self.slopeGroupIndex = -1
        ## Index of landuse group in Layers panel
        self.landuseGroupIndex = -1
        ## Index of soil group in Layers panel
        self.soilGroupIndex = -1
        ## Index of watershed group in Layers panel
        self.watershedGroupIndex = -1
        ## Index of results group in Layers panel
        self.resultsGroupIndex = -1
        ## Index of animation group in Layers panel
        self.animationGroupIndex = -1
        ## Flag showing if using existing watershed
        self.existingWshed = False
        ## Flag showing if using grid model
        self.useGridModel = False
        ## flag to show if using landscape units
        self.useLandscapes = False
        ## flag to show if dividing into left/right/headwater landscape units
        self.useLeftRight = False
        ## Path of DEM raster
        self.demFile = ''
        ## Path of filled DEM raster
        self.felFile = ''
        ## Path of stream burn-in shapefile
        self.burnFile = ''
        ## Path of DEM after burning-in
        self.burnedDemFile = ''
        ## Path of D8 flow direction raster
        self.pFile = ''
        ## Path of D8 flow accumulation raster
        self.ad8File = ''
        ## Path of subbasins raster
        self.basinFile = ''
        ## path of channel basins raster
        self.channelBasinFile = ''
        ## path of channel basins file with lakes masked out
        self.chBasinNoLakeFile = ''
        ## Path of channel raster
        self.srcChannelFile = ''
        ## Path of valleyDepthsFile
        # value at each point in this raster is the drop in metres
        # from the point to where its D8 flow path meets a channel
        # Channel elevations are measured at points adjacent to the channel
        # to avoid problems caused by burning-in
        self.valleyDepthsFile = ''
        ## Path of outlets shapefile
        self.outletFile = ''
        ## path of snapped outlets file
        self.snapFile = ''
        ## Path of outlets shapefile for extra reservoirs and point sources
        self.extraOutletFile = ''
        ## Path of stream shapefile
        self.streamFile = ''
        ## Path of stream shapefile calculated by delineation
        # since streamFile is set to streams from grid when using a grid model
        self.delinStreamFile = ''
        ## Path of channel shapefile
        self.channelFile = ''
        ## Path of subbasins shapefile or grid file when using grids
        self.subbasinsFile = ''
        ## Path of subbasins shapefile before lakes removed.  Not used with grid models.
        self.subsNoLakesFile = ''
        ## Path of watershed shapefile: shows channel basins.  Not used with grid models.
        self.wshedFile = ''
        ## Path of file like D8 contributing area but with heightened values at subbasin outlets
        self.hd8File = ''
        ## Path of distance to stream outlets raster
        self.distStFile = ''
        ## Path of distance to channel raster
        self.distChFile = ''
        ## Path of slope raster
        self.slopeFile = ''
        ## path of lakes shapefile
        self.lakeFile = ''
        ## Path of slope bands raster
        self.slopeBandsFile = ''
        ## Path of landuse raster
        self.landuseFile = ''
        ## Path of soil raster
        self.soilFile = ''
        ## path of floodplain raster
        self.floodFile = ''
        ## path of raster generated from playa lakes
        self.playaFile = ''
        ## Nodata value for DEM
        self.elevationNoData = 0.0
        ## DEM horizontal block size
        self.xBlockSize = 0
        ## DEM vertical block size
        self.yBlockSize = 0
        ## Nodata value for basins raster
        self.basinNoData = 0
        ## Nodata value for distance to outlets raster
        self.distStNoData = 0.0
        ## Nodata value for distance to channel raster
        self.distChNoData = 0.0
        ## Nodata value for slope raster
        self.slopeNoData = 0
        ## Nodata value for landuse raster
        self.cropNoData = 0
        ## Nodata value for soil raster
        self.soilNoData = 0
        ## Nodata value for floodplain raster
        self.floodNoData = -1 
        ## Area of DEM cell in square metres
        self.cellArea = 0.0
        ## channel threshold in square metres
        self.channelThresholdArea = 10000000.0 # 1000 hectares default
        ## gridSize as count of DEM cells per side (grid model only)
        self.gridSize = 0
        ## list of landuses exempt from HRU removal
        self.exemptLanduses: List[str] = []
        ## table of landuses being split
        self.splitLanduses: Dict[str, Dict[str, float]] = dict()
        ## Elevation bands threshold in metres
        self.elevBandsThreshold = 0
        ## Number of elevation bands
        self.numElevBands = 0
        ## Topology object
        self.topo: QSWATTopology = QSWATTopology(isBatch, isHUC)
        projFile: str = proj.fileName()
        projPath: str = QFileInfo(projFile).canonicalFilePath()
        pdir, base = os.path.split(projPath)
        ## Project name
        self.projName = os.path.splitext(base)[0]
        ## Project directory
        self.projDir = pdir
        ## QSWAT+ version
        self.version = version
        ## DEM directory
        self.demDir = ''
        ## Landuse directory
        self.landuseDir = ''
        ## Soil directory
        self.soilDir = ''
        ## Landscape directory
        self.landscapeDir = ''
        ## Floodplain directory
        self.floodDir = ''
        ## text directory
        self.textDir = ''
        ## Rasters directory
        self.rastersDir = ''
        ## Shapes directory
        self.shapesDir = ''
        ## Scenarios directory
        self.scenariosDir = ''
        ## Results directory
        self.resultsDir = ''
        ## Plots directory
        self.plotsDir = ''
        ## png directory for storing png images used to create animation videos
        self.pngDir = ''
        ## animation directory for storing animation files
        self.animationDir = ''
        self.createSubDirectories()
        ## path of full lsus shapefile
        self.fullLSUsFile = QSWATUtils.join(self.shapesDir, Parameters._LSUS1 + '.shp')
        ## path of actual lsus shapefile (after channel mergers
        self.actLSUsFile = QSWATUtils.join(self.shapesDir, Parameters._LSUS2 + '.shp')
        ## Path of FullHRUs shapefile
        self.fullHRUsFile = QSWATUtils.join(self.shapesDir, Parameters._HRUS1 + '.shp')
        ## Path of ActHRUs shapefile
        self.actHRUsFile = QSWATUtils.join(self.shapesDir, Parameters._HRUS2 + '.shp')
        ## Flag to show if running in batch mode
        self.isBatch = isBatch
        ## flag for HUC projects
        self.isHUC = isHUC
        ## log file for message output for HUC projects
        self.logFile = logFile
        ## Path of project database
        self.db: DBUtils = DBUtils(self.projDir, self.projName, self.dbProjTemplate, self.dbRefTemplate, self.isHUC, self.logFile, self.isBatch)
        ## multiplier to turn DEM distances to metres
        self.horizontalFactor = 1
        ## multiplier to turn elevations to metres
        self.verticalFactor = 1
        ## vertical units
        self.verticalUnits = Parameters._METRES
        # positions of sub windows
        ## Position of delineation form
        self.delineatePos = QPoint(0, 100)
        ## Position of HRUs form
        self.hrusPos = QPoint(0, 100)
        ## Position of parameters form
        self.parametersPos = QPoint(50, 100)
        ## Position of landscape form
        self.landscapePos = QPoint(50, 80)
        ## Position of select subbasins form
        self.selectSubsPos = QPoint(50, 100)
        ## Position of select reservoirs form
        self.selectResPos = QPoint(50, 100)
        ## Position of about form
        self.aboutPos = QPoint(50, 100)
        ## Position of elevation bands form
        self.elevationBandsPos = QPoint(50, 100)
        ## Position of split landuses form
        self.splitPos = QPoint(50, 100)
        ## Position of select landuses form
        self.selectLuPos = QPoint(50, 100)
        ## Position of exempt landuses form
        self.exemptPos = QPoint(50, 100)
        ## Position of outlets form
        self.outletsPos = QPoint(50, 100)
        ## Position of select outlets file form
        self.selectOutletFilePos = QPoint(50, 100)
        ## Position of select outlets form
        self.selectOutletPos = QPoint(50, 100)
        ## Position of visualise form
        self.visualisePos = QPoint(0, 100)
        ## rasters open that need to be closed if memory exception occurs
        self.openRasters: Set[Raster] = set()
        ## options for creating shapefiles
        self.vectorFileWriterOptions = QgsVectorFileWriter.SaveVectorOptions()
        self.vectorFileWriterOptions.ActionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
        self.vectorFileWriterOptions.driverName = "ESRI Shapefile"
        self.vectorFileWriterOptions.fileEncoding = "UTF-8"
        ## will set to choice made when converting from ArcSWAT, if that was how the project file was created
        # 0: Full
        # 1: Existing
        # 2: No GIS
        # NB These values are defined in convertFromArc.py
        self.fromArcChoice = -1
コード例 #25
0
    def testStartEditingCommitRollBack(self):

        ml = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer&field=int2:integer', 'test',
            'memory')
        self.assertTrue(ml.isValid())

        # Layer A geopackage A
        d = QTemporaryDir()
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'layer_a'
        err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
            ml, os.path.join(d.path(), 'test_EditBufferGroup_A.gpkg'),
            QgsCoordinateTransformContext(), options)

        self.assertEqual(err, QgsVectorFileWriter.NoError)
        self.assertTrue(os.path.isfile(newFileName))

        layer_a = QgsVectorLayer(newFileName + '|layername=layer_a')

        self.assertTrue(layer_a.isValid())

        # Layer B geopackage B
        options.layerName = 'layer_b'
        err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
            ml, os.path.join(d.path(), 'test_EditBufferGroup_B.gpkg'),
            QgsCoordinateTransformContext(), options)

        self.assertEqual(err, QgsVectorFileWriter.NoError)
        self.assertTrue(os.path.isfile(newFileName))

        layer_b = QgsVectorLayer(newFileName + '|layername=layer_b')

        self.assertTrue(layer_b.isValid())

        # Layer C memory
        layer_c = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer&field=int2:integer', 'test',
            'memory')
        self.assertTrue(layer_c.isValid())

        project = QgsProject()
        project.addMapLayers([layer_a, layer_b, layer_c])
        project.setTransactionMode(Qgis.TransactionMode.BufferedGroups)

        editBufferGroup = project.editBufferGroup()

        # Check layers in group
        self.assertIn(layer_a, editBufferGroup.layers())
        self.assertIn(layer_b, editBufferGroup.layers())
        self.assertIn(layer_c, editBufferGroup.layers())

        self.assertFalse(editBufferGroup.isEditing())

        self.assertTrue(editBufferGroup.startEditing())
        self.assertTrue(editBufferGroup.isEditing())
        self.assertTrue(layer_a.editBuffer())
        self.assertTrue(layer_b.editBuffer())
        self.assertTrue(layer_c.editBuffer())
        self.assertEqual(len(editBufferGroup.modifiedLayers()), 0)

        commitErrors = []
        self.assertTrue(editBufferGroup.commitChanges(commitErrors, False))
        self.assertTrue(editBufferGroup.isEditing())
        self.assertTrue(editBufferGroup.commitChanges(commitErrors, True))
        self.assertFalse(editBufferGroup.isEditing())

        self.assertTrue(editBufferGroup.startEditing())
        self.assertTrue(editBufferGroup.isEditing())

        f = QgsFeature(layer_a.fields())
        f.setAttribute('int', 123)
        f.setGeometry(QgsGeometry.fromWkt('point(7 45)'))
        self.assertTrue(layer_a.addFeatures([f]))
        self.assertEqual(len(editBufferGroup.modifiedLayers()), 1)
        self.assertIn(layer_a, editBufferGroup.modifiedLayers())

        # Check feature in layer edit buffer but not in provider till commit
        self.assertEqual(layer_a.featureCount(), 1)
        self.assertEqual(layer_a.dataProvider().featureCount(), 0)

        rollbackErrors = []
        self.assertTrue(editBufferGroup.rollBack(rollbackErrors, False))
        self.assertTrue(editBufferGroup.isEditing())
        self.assertEqual(layer_a.featureCount(), 0)

        self.assertTrue(layer_a.addFeatures([f]))
        self.assertEqual(layer_a.featureCount(), 1)
        self.assertEqual(layer_a.dataProvider().featureCount(), 0)

        self.assertTrue(editBufferGroup.commitChanges(commitErrors, True))
        self.assertFalse(editBufferGroup.isEditing())
        self.assertEqual(layer_a.featureCount(), 1)
        self.assertEqual(layer_a.dataProvider().featureCount(), 1)
コード例 #26
0
    def run(self):  # pylint: disable=missing-docstring,too-many-locals
        electorate_geometries, electorate_attributes = self.calculate_new_electorates()

        # we also need a dictionary of meshblock number to all electorate types
        meshblock_electorates = {}

        electorate_features = []

        for electorate_feature_id, attributes in electorate_attributes.items():
            electorate_code = attributes[self.ELECTORATE_CODE]
            geometry = electorate_geometries[electorate_feature_id]

            meshblocks = attributes[self.MESHBLOCKS]
            electorate_type = attributes[self.ELECTORATE_TYPE]
            name = attributes[self.ELECTORATE_NAME]

            for m in meshblocks:
                meshblock_number = m[self.meshblock_number_idx]
                if meshblock_number not in meshblock_electorates:
                    meshblock_electorates[meshblock_number] = {}
                meshblock_electorates[meshblock_number][electorate_type] = electorate_code

            electorate_feature = QgsFeature()
            electorate_feature.setGeometry(geometry)
            electorate_feature.setAttributes([electorate_type, electorate_code, name])
            electorate_features.append(electorate_feature)

        electorate_layer = QgsVectorLayer(
            "Polygon?crs=EPSG:2193&field=type:string(2)&field=code:string&field=name:string",
            "source", "memory")
        if not electorate_layer.dataProvider().addFeatures(electorate_features):
            return False

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'electorates'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
        error, self.message = QgsVectorFileWriter.writeAsVectorFormat(electorate_layer, self.dest_file, options)
        if error:
            return False

        layer = QgsVectorLayer(
            "NoGeometry?field=meshblock_number:int&field=gn_code:string&field=gs_code:string&field=m_code:string",
            "source", "memory")
        meshblock_features = []
        for meshblock_number, electorates in meshblock_electorates.items():
            f = QgsFeature()
            gn = electorates[self.GN] if self.GN in electorates else NULL
            gs = electorates[self.GS] if self.GS in electorates else NULL
            m = electorates[self.M] if self.M in electorates else NULL
            f.setAttributes([meshblock_number, gn, gs, m])
            meshblock_features.append(f)

        layer.dataProvider().addFeatures(meshblock_features)
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'meshblocks'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer

        error, self.message = QgsVectorFileWriter.writeAsVectorFormat(layer, self.dest_file, options)
        if error:
            return False

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'user_log'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer

        error, self.message = QgsVectorFileWriter.writeAsVectorFormat(self.user_log_layer, self.dest_file, options)
        if error:
            return False

        return True
コード例 #27
0
    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

        if self.first_start == True:
            self.first_start = False
            self.dlg = SurvexImportDialog()
            self.dlg.selectedFile.clear()
            self.dlg.fileSelector.clicked.connect(self.select_3d_file)
            self.dlg.selectedGPKG.clear()
            self.dlg.GPKGSelector.clicked.connect(self.select_gpkg)
            self.dlg.CRSFromProject.setChecked(False)
            self.dlg.CRSFromFile.clicked.connect(self.crs_from_file)
            self.dlg.CRSFromFile.setChecked(False)
            self.dlg.CRSFromProject.clicked.connect(self.crs_from_project)
            self.dlg.ImportAll.clicked.connect(self.toggle_import_all)
            self.dlg.Legs.clicked.connect(self.all_checked)
            self.dlg.Stations.clicked.connect(self.all_checked)
            self.dlg.Polygons.clicked.connect(self.all_checked)
            self.dlg.Walls.clicked.connect(self.all_checked)
            self.dlg.XSections.clicked.connect(self.all_checked)
            self.dlg.Traverses.clicked.connect(self.all_checked)
            self.dlg.LegsSurface.clicked.connect(self.all_checked)
            self.dlg.LegsSplay.clicked.connect(self.all_checked)
            self.dlg.LegsDuplicate.clicked.connect(self.all_checked)
            self.dlg.StationsSurface.clicked.connect(self.all_checked)

        self.dlg.show()  # show the dialog

        result = self.dlg.exec_()  # Run the dialog event loop

        if result:  # The user pressed OK, and this is what happened next!

            survex_3d = self.dlg.selectedFile.text()
            gpkg_file = self.dlg.selectedGPKG.text()

            include_legs = self.dlg.Legs.isChecked()
            include_stations = self.dlg.Stations.isChecked()
            include_polygons = self.dlg.Polygons.isChecked()
            include_walls = self.dlg.Walls.isChecked()
            include_xsections = self.dlg.XSections.isChecked()
            include_traverses = self.dlg.Traverses.isChecked()

            exclude_surface_legs = not self.dlg.LegsSurface.isChecked()
            exclude_splay_legs = not self.dlg.LegsSplay.isChecked()
            exclude_duplicate_legs = not self.dlg.LegsDuplicate.isChecked()

            exclude_surface_stations = not self.dlg.StationsSurface.isChecked()

            use_clino_wgt = self.dlg.UseClinoWeights.isChecked()
            include_up_down = self.dlg.IncludeUpDown.isChecked()

            discard_features = not self.dlg.KeepFeatures.isChecked()

            if not os.path.exists(survex_3d):
                raise Exception("File '%s' doesn't exist" % survex_3d)

            if discard_features:
                self.leg_list = []
                self.station_list = []
                self.station_xyz = {}
                self.xsect_list = []

            # Read .3d file as binary, parse, and save data structures

            with open(survex_3d, 'rb') as fp:

                line = fp.readline().rstrip()  # File ID check

                if not line.startswith(b'Survex 3D Image File'):
                    raise IOError('Not a survex .3d file: ' + survex_3d)

                line = fp.readline().rstrip()  # File format version

                if not line.startswith(b'v'):
                    raise IOError('Unrecognised survex .3d version in ' +
                                  survex_3d)

                version = int(line[1:])
                if version < 8:
                    raise IOError('Survex .3d version >= 8 required in ' +
                                  survex_3d)

                line = fp.readline().rstrip(
                )  # Metadata (title and coordinate system)
                fields = line.split(b'\x00')

                previous_title = '' if discard_features else self.title

                if previous_title:
                    self.title = previous_title + ' + ' + fields[0].decode(
                        'ascii')
                else:
                    self.title = fields[0].decode('ascii')

                self.set_crs(
                    fields[1].decode('ascii') if len(fields) > 1 else None)

                line = fp.readline().rstrip(
                )  # Timestamp, unused in present application

                if not line.startswith(b'@'):
                    raise IOError('Unrecognised timestamp in ' + survex_3d)

                # timestamp = int(line[1:])

                flag = ord(fp.read(1))  # file-wide flag

                if flag & 0x80:  # abort if extended elevation
                    raise IOError("Can't deal with extended elevation in " +
                                  survex_3d)

                # All file-wide header data read in, now read byte-wise
                # according to .3d spec.  Note that all elements must
                # be processed, in order, otherwise we get out of sync.

                # We first define some baseline dates

                date0 = QDate(1900, 1, 1)
                date1 = QDate(1900, 1, 1)
                date2 = QDate(1900, 1, 1)

                label, style = '', 0xff  # initialise label and style

                legs = []  # will be used to capture leg data between MOVEs
                xsect = []  # will be used to capture XSECT data
                nlehv = None  # .. remains None if there isn't any error data...

                while True:  # start of byte-gobbling while loop

                    char = fp.read(1)

                    if not char:  # End of file (reached prematurely?)
                        raise IOError('Premature end of file in ' + survex_3d)

                    byte = ord(char)

                    if byte <= 0x05:  # STYLE
                        if byte == 0x00 and style == 0x00:  # this signals end of data
                            if legs:  # there may be a pending list of legs to save
                                self.leg_list.append((legs, nlehv))
                            break  # escape from byte-gobbling while loop
                        else:
                            style = byte

                    elif byte <= 0x0e:  # Reserved
                        continue

                    elif byte == 0x0f:  # MOVE
                        xyz = self.read_xyz(fp)
                        if legs:
                            self.leg_list.append((legs, nlehv))
                            legs = []

                    elif byte == 0x10:  # DATE (none)
                        date1 = date2 = date0

                    elif byte == 0x11:  # DATE (single date)
                        days = unpack('<H', fp.read(2))[0]
                        date1 = date2 = date0.addDays(days)

                    elif byte == 0x12:  # DATE (date range, short format)
                        days, extra = unpack('<HB', fp.read(3))
                        date1 = date0.addDays(days)
                        date2 = date0.addDays(days + extra + 1)

                    elif byte == 0x13:  # DATE (date range, long format)
                        days1, days2 = unpack('<HH', fp.read(4))
                        date1 = date0.addDays(days1)
                        date2 = date0.addDays(days2)

                    elif byte <= 0x1e:  # Reserved
                        continue

                    elif byte == 0x1f:  # Error info
                        nlehv = unpack('<iiiii', fp.read(20))

                    elif byte <= 0x2f:  # Reserved
                        continue

                    elif byte <= 0x33:  # XSECT
                        label = self.read_label(fp, label)
                        if byte & 0x02:
                            lrud = unpack('<iiii', fp.read(16))
                        else:
                            lrud = unpack('<hhhh', fp.read(8))
                        xsect.append((label, lrud))
                        if byte & 0x01:  # XSECT_END
                            self.xsect_list.append(xsect)
                            xsect = []

                    elif byte <= 0x3f:  # Reserved
                        continue

                    elif byte <= 0x7f:  # LINE
                        flag = byte & 0x3f
                        if not (flag & 0x20):
                            label = self.read_label(fp, label)
                        xyz_prev = xyz
                        xyz = self.read_xyz(fp)
                        while (True):  # code pattern to implement logic
                            if exclude_surface_legs and flag & 0x01: break
                            if exclude_duplicate_legs and flag & 0x02: break
                            if exclude_splay_legs and flag & 0x04: break
                            legs.append(((xyz_prev, xyz), label, style, date1,
                                         date2, flag))
                            break

                    elif byte <= 0xff:  # LABEL (or NODE)
                        flag = byte & 0x7f
                        label = self.read_label(fp, label)
                        xyz = self.read_xyz(fp)
                        while (True):  # code pattern to implement logic
                            if exclude_surface_stations and flag & 0x01 and not flag & 0x02:
                                break
                            self.station_list.append((xyz, label, flag))
                            break
                        self.station_xyz[label] = xyz

                # End of byte-gobbling while loop

            # file closes automatically, with open(survex_3d, 'rb') as fp:

            layers = []  # used to keep a list of the created layers

            if include_stations and self.station_list:  # station layer

                station_layer = self.add_layer('stations', 'PointZ')

                attrs = [
                    QgsField(self.station_attr[k], QVariant.Int)
                    for k in self.station_flags
                ]
                attrs.insert(0, QgsField('ELEVATION', QVariant.Double))
                attrs.insert(0, QgsField('NAME', QVariant.String))
                station_layer.dataProvider().addAttributes(attrs)
                station_layer.updateFields()

                features = []

                for (xyz, label, flag) in self.station_list:
                    xyz = [0.01 * v for v in xyz]
                    attrs = [1 if flag & k else 0 for k in self.station_flags]
                    attrs.insert(0, round(xyz[2], 2))  # elevation
                    attrs.insert(0, label)
                    feat = QgsFeature()
                    geom = QgsGeometry(QgsPoint(*xyz))
                    feat.setGeometry(geom)
                    feat.setAttributes(attrs)
                    features.append(feat)

                station_layer.dataProvider().addFeatures(features)
                layers.append(station_layer)

            if include_legs and self.leg_list:  # leg layer

                leg_layer = self.add_layer('legs', 'LineStringZ')

                attrs = [
                    QgsField(self.leg_attr[k], QVariant.Int)
                    for k in self.leg_flags
                ]
                if nlehv:
                    [
                        attrs.insert(0, QgsField(s, QVariant.Double))
                        for s in self.error_fields
                    ]
                    attrs.insert(0, QgsField('NLEGS', QVariant.Int))
                attrs.insert(0, QgsField('DATE2', QVariant.Date))
                attrs.insert(0, QgsField('DATE1', QVariant.Date))
                attrs.insert(0, QgsField('STYLE', QVariant.String))
                attrs.insert(0, QgsField('ELEVATION', QVariant.Double))
                attrs.insert(0, QgsField('NAME', QVariant.String))
                leg_layer.dataProvider().addAttributes(attrs)
                leg_layer.updateFields()

                features = []

                for legs, nlehv in self.leg_list:
                    for (xyz_pair, label, style, from_date, to_date,
                         flag) in legs:
                        elev = 0.5 * sum([0.01 * xyz[2] for xyz in xyz_pair])
                        points = []
                        for xyz in xyz_pair:
                            xyz = [0.01 * v for v in xyz]
                            points.append(QgsPoint(*xyz))
                        attrs = [1 if flag & k else 0 for k in self.leg_flags]
                        if nlehv:
                            [
                                attrs.insert(0, 0.01 * v)
                                for v in reversed(nlehv[1:5])
                            ]
                            attrs.insert(0, nlehv[0])
                        attrs.insert(0, to_date)
                        attrs.insert(0, from_date)
                        attrs.insert(0, self.style_type[style])
                        attrs.insert(0, round(elev, 2))
                        attrs.insert(0, label)
                        linestring = QgsLineString()
                        linestring.setPoints(points)
                        feat = QgsFeature()
                        geom = QgsGeometry(linestring)
                        feat.setGeometry(geom)
                        feat.setAttributes(attrs)
                        features.append(feat)

                leg_layer.dataProvider().addFeatures(features)
                layers.append(leg_layer)

            # Now do wall features if asked

            if (include_traverses or include_xsections or include_walls
                    or include_polygons) and self.xsect_list:

                trav_features = []
                wall_features = []
                xsect_features = []
                quad_features = []

                for xsect in self.xsect_list:

                    if len(xsect) < 2:  # if there's only one station ..
                        continue  # .. give up as we don't know which way to face

                    centerline = [
                    ]  # will contain the station position and LRUD data

                    for label, lrud in xsect:
                        xyz = self.station_xyz[
                            label]  # look up coordinates from label
                        lrud_or_zero = tuple([max(0, v) for v in lrud
                                              ])  # deal with missing data
                        centerline.append(
                            xyz + lrud_or_zero)  # and collect as 7-uple

                    direction = [
                    ]  # will contain the corresponding direction vectors

                    # The calculations below use integers for xyz and lrud, and
                    # conversion to metres is left to the end.  Then dh2 is an
                    # integer and the test for a plumb is safely dh2 = 0.

                    # The directions are unit vectors optionally weighted by
                    # cos(inclination) = dh/dl where dh^2 = dx^2 + dy^2 (note, no dz^2),
                    # and dl^2 = dh^2 + dz^2.  The normalisation is correspondingly
                    # either 1/dh, or 1/dh * dh/dl = 1/dl.

                    for i, xyzlrud in enumerate(centerline):
                        x, y, z = xyzlrud[0:3]
                        if i > 0:
                            dx, dy, dz = x - xp, y - yp, z - zp
                            dh2 = dx * dx + dy * dy  # integer horizontal displacement (mm^2)
                            norm = sqrt(dh2 + dz *
                                        dz) if use_clino_wgt else sqrt(dh2)
                            dx, dy = (dx / norm, dy /
                                      norm) if dh2 > 0 and norm > 0 else (0, 0)
                            direction.append((dx, dy))
                        xp, yp, zp = x, y, z

                    left_wall = []
                    right_wall = []
                    up_down = []

                    # We build the walls by walking through the list
                    # of stations and directions, with simple defaults
                    # for the start and end stations

                    for i, (x, y, z, l, r, u, d) in enumerate(centerline):
                        d1x, d1y = direction[i - 1] if i > 0 else (0, 0)
                        d2x, d2y = direction[i] if i + 1 < len(
                            centerline) else (0, 0)
                        dx, dy = d1x + d2x, d1y + d2y  # mean (sum of) direction vectors
                        norm = sqrt(dx * dx +
                                    dy * dy)  # normalise to unit vector
                        ex, ey = (dx / norm, dy / norm) if norm > 0 else (0, 0)
                        # Convert to metres when saving the points
                        left_wall.append((0.01 * (x - l * ey),
                                          0.01 * (y + l * ex), 0.01 * z))
                        right_wall.append((0.01 * (x + r * ey),
                                           0.01 * (y - r * ex), 0.01 * z))
                        up_down.append((0.01 * u, 0.01 * d))

                    # Mean elevation of centerline, used for elevation attribute

                    elev = 0.01 * sum([xyzlrud[2] for xyzlrud in centerline
                                       ]) / len(centerline)
                    attrs = [round(elev, 2)]

                    # Now create the feature sets - first the centerline traverse

                    points = []

                    for xyzlrud in centerline:
                        xyz = [0.01 * v for v in xyzlrud[0:3]
                               ]  # These were mm, convert to metres
                        points.append(QgsPoint(*xyz))

                    linestring = QgsLineString()
                    linestring.setPoints(points)
                    feat = QgsFeature()
                    geom = QgsGeometry(linestring)
                    feat.setGeometry(geom)
                    feat.setAttributes(attrs)
                    trav_features.append(feat)

                    # The walls as line strings

                    for wall in (left_wall, right_wall):

                        points = [QgsPoint(*xyz) for xyz in wall]
                        linestring = QgsLineString()
                        linestring.setPoints(points)
                        feat = QgsFeature()
                        geom = QgsGeometry(linestring)
                        feat.setGeometry(geom)
                        feat.setAttributes(attrs)
                        wall_features.append(feat)

                    # Slightly more elaborate, pair up points on left
                    # and right walls, and build a cross section as a
                    # 2-point line string, and a quadrilateral polygon
                    # with a closed 5-point line string for the
                    # exterior ring.  Note that QGIS polygons are
                    # supposed to have their points ordered clockwise.

                    for i, xyz_pair in enumerate(zip(left_wall, right_wall)):

                        elev = 0.01 * centerline[i][
                            2]  # elevation of station in centerline
                        attrs = [round(elev, 2)]
                        points = [QgsPoint(*xyz) for xyz in xyz_pair]
                        linestring = QgsLineString()
                        linestring.setPoints(points)
                        feat = QgsFeature()
                        geom = QgsGeometry(linestring)
                        feat.setGeometry(geom)
                        feat.setAttributes(attrs)
                        xsect_features.append(feat)

                        if i > 0:
                            elev = 0.5 * (prev_xyz_pair[0][2] + xyz_pair[0][2]
                                          )  # average elevation
                            attrs = [round(elev, 2)]
                            if include_up_down:  # average up / down
                                attrs += [
                                    0.5 * (v1 + v2)
                                    for (v1,
                                         v2) in zip(up_down[i - 1], up_down[i])
                                ]
                            points = [
                            ]  # will contain the exterior 5-point ring, as follows...
                            for xyz in tuple(
                                    reversed(prev_xyz_pair)) + xyz_pair + (
                                        prev_xyz_pair[1], ):
                                points.append(QgsPoint(*xyz))
                            linestring = QgsLineString()
                            linestring.setPoints(points)
                            polygon = QgsPolygon()
                            polygon.setExteriorRing(linestring)
                            feat = QgsFeature()
                            geom = QgsGeometry(polygon)
                            feat.setGeometry(geom)
                            feat.setAttributes(attrs)
                            quad_features.append(feat)

                        prev_xyz_pair = xyz_pair

                # End of processing xsect_list - now add features to requested layers

                attrs = [QgsField('ELEVATION',
                                  QVariant.Double)]  # common to all

                if include_traverses and trav_features:  # traverse layer
                    travs_layer = self.add_layer('traverses', 'LineStringZ')
                    travs_layer.dataProvider().addAttributes(attrs)
                    travs_layer.updateFields()
                    travs_layer.dataProvider().addFeatures(trav_features)
                    layers.append(travs_layer)

                if include_xsections and xsect_features:  # xsection layer
                    xsects_layer = self.add_layer('xsections', 'LineStringZ')
                    xsects_layer.dataProvider().addAttributes(attrs)
                    xsects_layer.updateFields()
                    xsects_layer.dataProvider().addFeatures(xsect_features)
                    layers.append(xsects_layer)

                if include_walls and wall_features:  # wall layer
                    walls_layer = self.add_layer('walls', 'LineStringZ')
                    walls_layer.dataProvider().addAttributes(attrs)
                    walls_layer.updateFields()
                    walls_layer.dataProvider().addFeatures(wall_features)
                    layers.append(walls_layer)

                if include_up_down:  # add fields if requested for polygons
                    attrs += [
                        QgsField(s, QVariant.Double)
                        for s in ('MEAN_UP', 'MEAN_DOWN')
                    ]

                if include_polygons and quad_features:  # polygon layer
                    quads_layer = self.add_layer('polygons', 'PolygonZ')
                    quads_layer.dataProvider().addAttributes(attrs)
                    quads_layer.updateFields()
                    quads_layer.dataProvider().addFeatures(quad_features)
                    layers.append(quads_layer)

            # All layers have been created, now update extents and add to QGIS registry

            if layers:
                [layer.updateExtents() for layer in layers]
                QgsProject.instance().addMapLayers(layers)

            # Write to GeoPackage if requested

            if gpkg_file:
                opts = [
                    QgsVectorFileWriter.CreateOrOverwriteFile,
                    QgsVectorFileWriter.CreateOrOverwriteLayer
                ]
                for i, layer in enumerate(layers):
                    options = QgsVectorFileWriter.SaveVectorOptions()
                    options.actionOnExistingFile = opts[int(
                        i > 0)]  # create file or layer
                    layer_name = layer.name()
                    match = search(
                        ' - ([a-z]*)',
                        layer_name)  # ie, extract 'legs', 'stations', etc
                    options.layerName = str(
                        match.group(1)) if match else layer_name
                    writer = QgsVectorFileWriter.writeAsVectorFormat(
                        layer, gpkg_file, options)
                    if writer:
                        msg = "'{}' -> {} in {}".format(
                            layer_name, options.layerName, gpkg_file)
                        QgsMessageLog.logMessage(msg,
                                                 tag='Import .3d',
                                                 level=Qgis.Info)
                    options, writer = None, None
コード例 #28
0
    def _init_ext_layer(self, geom_str, idx, crs):
        """given non map of feat, init a qgis layer
        :map_feat: {geom_string: list_of_feat}
        """
        ext = self.ext
        driver_name = ext.upper()  # might not needed for

        layer_name = self._layer_name(geom_str, idx)

        # sqlite max connection 64
        # if xyz space -> more than 64 vlayer,
        # then create new fname

        # fname = make_unique_full_path(ext=ext)
        fname = make_fixed_full_path(self._layer_fname(), ext=ext)
        if geom_str:
            geomz = geom_str if geom_str.endswith("Z") else "{}Z".format(
                geom_str)
        else:
            geomz = "NoGeometry"
        vlayer = QgsVectorLayer("{geom}?crs={crs}&index=yes".format(geom=geomz,
                                                                    crs=crs),
                                layer_name,
                                "memory")  # this should be done in main thread

        # QgsVectorFileWriter.writeAsVectorFormat(vlayer, fname, "UTF-8", vlayer.sourceCrs(),
        # driver_name)

        db_layer_name = self._db_layer_name(geom_str, idx)

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.fileEncoding = "UTF-8"
        options.driverName = driver_name
        options.ct = QgsCoordinateTransform(vlayer.sourceCrs(),
                                            vlayer.sourceCrs(),
                                            QgsProject.instance())
        options.layerName = db_layer_name
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer  # update mode
        if hasattr(QgsVectorFileWriter, "writeAsVectorFormatV2"):
            err = QgsVectorFileWriter.writeAsVectorFormatV2(
                vlayer, fname, vlayer.transformContext(), options)
        else:
            err = QgsVectorFileWriter.writeAsVectorFormat(
                vlayer, fname, options)
        if err[0] == QgsVectorFileWriter.ErrCreateDataSource:
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
            if hasattr(QgsVectorFileWriter, "writeAsVectorFormatV2"):
                err = QgsVectorFileWriter.writeAsVectorFormatV2(
                    vlayer, fname, vlayer.transformContext(), options)
            else:
                err = QgsVectorFileWriter.writeAsVectorFormat(
                    vlayer, fname, options)
        if err[0] != QgsVectorFileWriter.NoError:
            raise Exception("%s: %s" % err)

        self._update_constraint_trigger(fname, db_layer_name)

        uri = "%s|layername=%s" % (fname, db_layer_name)
        vlayer = QgsVectorLayer(uri, layer_name, "ogr")
        self._save_meta_vlayer(vlayer)

        return vlayer
コード例 #29
0
    def testOverwriteLayer(self):
        """Tests writing a layer with a field value converter."""

        ml = QgsVectorLayer('Point?field=firstfield:int', 'test', 'memory')
        provider = ml.dataProvider()

        ft = QgsFeature()
        ft.setAttributes([1])
        provider.addFeatures([ft])

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        filename = '/vsimem/out.gpkg'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        ds = ogr.Open(filename, update=1)
        lyr = ds.GetLayerByName('test')
        self.assertIsNotNone(lyr)
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 1)
        ds.CreateLayer('another_layer')
        del f
        del lyr
        del ds

        caps = QgsVectorFileWriter.editionCapabilities(filename)
        self.assertTrue((caps & QgsVectorFileWriter.CanAddNewLayer))
        self.assertTrue((caps & QgsVectorFileWriter.CanAppendToExistingLayer))
        self.assertTrue(
            (caps & QgsVectorFileWriter.CanAddNewFieldsToExistingLayer))
        self.assertTrue((caps & QgsVectorFileWriter.CanDeleteLayer))

        self.assertTrue(QgsVectorFileWriter.targetLayerExists(
            filename, 'test'))

        self.assertFalse(
            QgsVectorFileWriter.areThereNewFieldsToCreate(
                filename, 'test', ml, [0]))

        # Test CreateOrOverwriteLayer
        ml = QgsVectorLayer('Point?field=firstfield:int', 'test', 'memory')
        provider = ml.dataProvider()

        ft = QgsFeature()
        ft.setAttributes([2])
        provider.addFeatures([ft])

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
        filename = '/vsimem/out.gpkg'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        ds = ogr.Open(filename)
        lyr = ds.GetLayerByName('test')
        self.assertIsNotNone(lyr)
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 2)
        # another_layer should still exist
        self.assertIsNotNone(ds.GetLayerByName('another_layer'))
        del f
        del lyr
        del ds

        # Test CreateOrOverwriteFile
        ml = QgsVectorLayer('Point?field=firstfield:int', 'test', 'memory')
        provider = ml.dataProvider()

        ft = QgsFeature()
        ft.setAttributes([3])
        provider.addFeatures([ft])

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        filename = '/vsimem/out.gpkg'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        ds = ogr.Open(filename)
        lyr = ds.GetLayerByName('test')
        self.assertIsNotNone(lyr)
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 3)
        # another_layer should no longer exist
        self.assertIsNone(ds.GetLayerByName('another_layer'))
        del f
        del lyr
        del ds

        # Test AppendToLayerNoNewFields
        ml = QgsVectorLayer('Point?field=firstfield:int&field=secondfield:int',
                            'test', 'memory')
        provider = ml.dataProvider()

        ft = QgsFeature()
        ft.setAttributes([4, -10])
        provider.addFeatures([ft])

        self.assertTrue(
            QgsVectorFileWriter.areThereNewFieldsToCreate(
                filename, 'test', ml, [0, 1]))

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        options.actionOnExistingFile = QgsVectorFileWriter.AppendToLayerNoNewFields
        filename = '/vsimem/out.gpkg'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        ds = ogr.Open(filename)
        lyr = ds.GetLayerByName('test')
        self.assertEqual(lyr.GetLayerDefn().GetFieldCount(), 1)
        self.assertIsNotNone(lyr)
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 3)
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 4)
        del f
        del lyr
        del ds

        # Test AppendToLayerAddFields
        ml = QgsVectorLayer('Point?field=firstfield:int&field=secondfield:int',
                            'test', 'memory')
        provider = ml.dataProvider()

        ft = QgsFeature()
        ft.setAttributes([5, -1])
        provider.addFeatures([ft])

        self.assertTrue(
            QgsVectorFileWriter.areThereNewFieldsToCreate(
                filename, 'test', ml, [0, 1]))

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        options.actionOnExistingFile = QgsVectorFileWriter.AppendToLayerAddFields
        filename = '/vsimem/out.gpkg'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        ds = ogr.Open(filename)
        lyr = ds.GetLayerByName('test')
        self.assertEqual(lyr.GetLayerDefn().GetFieldCount(), 2)
        self.assertIsNotNone(lyr)
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 3)
        if hasattr(f, "IsFieldSetAndNotNull"):
            # GDAL >= 2.2
            self.assertFalse(f.IsFieldSetAndNotNull('secondfield'))
        else:
            self.assertFalse(f.IsFieldSet('secondfield'))
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 4)
        if hasattr(f, "IsFieldSetAndNotNull"):
            self.assertFalse(f.IsFieldSetAndNotNull('secondfield'))
        else:
            self.assertFalse(f.IsFieldSet('secondfield'))
        f = lyr.GetNextFeature()
        self.assertEqual(f['firstfield'], 5)
        self.assertEqual(f['secondfield'], -1)
        del f
        del lyr
        del ds

        gdal.Unlink(filename)
コード例 #30
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        source_pts = self.parameterAsSource(parameters, self.INPUT_POINTS,
                                            context)
        input_field = self.parameterAsString(parameters, self.INPUT_FIELD,
                                             context)
        source_dem = self.parameterAsRasterLayer(parameters, self.INPUT_DEM,
                                                 context)
        out_directory = self.parameterAsString(parameters, self.OUTPUT_DIR,
                                               context)
        out_type_nr = self.parameterAsInt(parameters, self.OUTPUT_TYPE,
                                          context)
        out_type = QgsVectorFileWriter.supportedFormatExtensions(
        )[:2][out_type_nr]
        to_gpkg = out_type == 'gpkg'
        load_results = self.parameterAsBool(parameters, self.LOAD_RESULTS,
                                            context)
        if source_pts is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_POINTS))
        if source_dem is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_DEM))

        feedback.pushInfo("Input data loaded! Creating catchments...")
        feedback.setProgress(1)

        unique_field = input_field if input_field else ""
        if unique_field:
            field_idx = source_pts.fields().lookupField(unique_field)
            unique_values = source_pts.uniqueValues(field_idx)
        else:
            unique_values = [f.id() for f in source_pts.getFeatures()]

        feedback.pushInfo(f"Creating directory: {out_directory}")
        mkdir(out_directory)
        bname = f"catchment{'s' if to_gpkg else ''}"
        output_basename = os.path.join(out_directory, bname)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        total_nr = len(unique_values)
        total = 100. / total_nr if source_pts.featureCount() else 1
        output_layers = []

        for i, unique_value in enumerate(unique_values):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            table = f"catchment_{unique_value}" if to_gpkg else ""
            file_mod = "" if to_gpkg else f"_{unique_value}"
            filename = f"{output_basename}{file_mod}"
            destination = f"{filename}.{out_type}"
            output_uri = destination + (f"|layername={table}"
                                        if to_gpkg else "")
            feedback.pushInfo(
                self.tr('Creating layer: {}').format(destination))

            if unique_field:
                req_filter = f"{QgsExpression.quotedColumnRef(unique_field)}={QgsExpression.quotedValue(unique_value)}"
                req = QgsFeatureRequest().setFilterExpression(req_filter)
            else:
                req = QgsFeatureRequest(unique_value)  # feature id

            for source_pt in source_pts.getFeatures(req):
                if feedback.isCanceled():
                    break

                # Get x and y coordinate from point feature
                geom = source_pt.geometry()
                p = geom.asPoint()
                x = p.x()
                y = p.y()

                feedback.pushInfo(
                    'Creating upslope area for point ({:.2f}, {:.2f}) - {} of {}'
                    .format(x, y, i + 1, total_nr))

                # Calculate catchment raster from point feature
                catchraster = processing.run(
                    "saga:upslopearea",
                    {
                        'TARGET': None,
                        'TARGET_PT_X': x,
                        'TARGET_PT_Y': y,
                        'ELEVATION': source_dem,
                        'SINKROUTE': None,
                        'METHOD': 0,
                        'CONVERGE': 1.1,
                        'AREA': 'TEMPORARY_OUTPUT'
                    },
                    context=context,
                    feedback=feedback,
                )

                # Polygonize raster catchment
                catchpoly = processing.run(
                    "gdal:polygonize",
                    {
                        'INPUT': catchraster["AREA"],
                        'BAND': 1,
                        'FIELD': 'DN',
                        'EIGHT_CONNECTEDNESS': False,
                        'OUTPUT': 'TEMPORARY_OUTPUT'
                    },
                    context=context,
                    feedback=feedback,
                )

                # Select features having DN = 100
                catchpoly_lyr = QgsProcessingUtils.mapLayerFromString(
                    catchpoly["OUTPUT"], context=context)
                catchpoly_lyr.selectByExpression('"DN"=100')

                options = QgsVectorFileWriter.SaveVectorOptions()
                options.driverName = "GPKG" if to_gpkg else "ESRI Shapefile"
                options.layerName = table
                options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
                options.onlySelectedFeatures = True
                trans_context = QgsCoordinateTransformContext()

                write_result, error_message = QgsVectorFileWriter.writeAsVectorFormatV2(
                    catchpoly_lyr, destination, trans_context, options)
                if write_result != 0:
                    feedback.pushInfo(f"Initial write failed: {error_message}")
                    # retry with option for creating the dataset
                    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
                    write_result, error_message = QgsVectorFileWriter.writeAsVectorFormatV2(
                        catchpoly_lyr, destination, trans_context, options)

                feedback.pushInfo(
                    f"Final write attempt: {write_result} == 0 -> SUCCESS or {error_message}"
                )

                output_layer = QgsProcessingUtils.mapLayerFromString(
                    output_uri, context=context)
                output_layers.append(output_uri)
                if load_results:
                    context.temporaryLayerStore().addMapLayer(output_layer)
                    context.addLayerToLoadOnCompletion(
                        output_layer.id(),
                        QgsProcessingContext.LayerDetails(
                            table if to_gpkg else f"catchment {unique_value}",
                            context.project(), self.OUTPUT_LAYERS))

            feedback.setProgress(int((i + 1) * total))

        return {
            self.OUTPUT_DIR: out_directory,
            self.OUTPUT_LAYERS: output_layers
        }