Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
spatialthoughts committed Jul 24, 2023
1 parent d177d70 commit faf9da1
Show file tree
Hide file tree
Showing 18 changed files with 548 additions and 309 deletions.
11 changes: 1 addition & 10 deletions code/pyqgis/save_attributes_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@
output_name = 'output.csv'
output_path = os.path.join(data_dir, output_name)

# We will use QgsVectorFileWriter.create() method
# It takes the following parameters
# fileName: Path to the file
# fields: Fields to write
# geometryType: geometry type of output file
# srs: CRS of the output file
# transformContext: Datum transformation settings
# options: Save Options such as format, encoding etc.

# Define the options for saving the layer
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = 'CSV'
Expand All @@ -40,7 +31,7 @@
fields=layer.fields(),
geometryType=QgsWkbTypes.NoGeometry,
srs=layer.crs(),
transformContext=transform_context,
transformContext=QgsProject.instance().transformContext(),
options=save_options)

# Check if we were able to create the writer
Expand Down
55 changes: 32 additions & 23 deletions code/pyqgis/save_attributes_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,63 @@
from qgis.core import (QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterEnum,
QgsProcessingParameterFileDestination,
QgsWkbTypes)
QgsVectorFileWriter,
QgsWkbTypes,
QgsProject)


class SaveAttributesAlgorithm(QgsProcessingAlgorithm):
"""Saves the attributes of a vector layer to a CSV file."""
OUTPUT = 'OUTPUT'
INPUT = 'INPUT'

def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterFeatureSource(
self.INPUT,
self.tr('Input layer'),
'INPUT',
'Input layer',
[QgsProcessing.TypeVectorAnyGeometry]
)
)

# We add a file output of type CSV.
self.addParameter(
QgsProcessingParameterFileDestination(
self.OUTPUT,
self.tr('Output File'),
'OUTPUT',
'Output File',
'CSV files (*.csv)',
)
)

def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(
layer = self.parameterAsVectorLayer(
parameters,
self.INPUT,
'INPUT',
context)

sink, output = self.parameterAsSink(
parameters,
self.OUTPUT,
context,
source.fields(),
QgsWkbTypes.NoGeometry,
source.sourceCrs()
)

fieldnames = [field.name() for field in source.fields()]
output = self.parameterAsFileOutput(
parameters,
'OUTPUT',
context)

# Compute the number of steps to display within the progress bar and
# get features from source
total = 100.0 / source.featureCount() if source.featureCount() else 0
features = source.getFeatures()
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
features = layer.getFeatures()

# Define the options for saving the layer
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = 'CSV'
save_options.fileEncoding = 'UTF-8'

# Create the writer
writer = QgsVectorFileWriter.create(
fileName=output,
fields=layer.fields(),
geometryType=QgsWkbTypes.NoGeometry,
srs=layer.crs(),
transformContext=QgsProject.instance().transformContext(),
options=save_options)


for current, f in enumerate(features):
Expand All @@ -58,12 +67,12 @@ def processAlgorithm(self, parameters, context, feedback):
break

# Add a feature in the sink
sink.addFeature(f)
writer.addFeature(f)

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

return {self.OUTPUT: output}
return {'OUTPUT': output}

def name(self):
return 'save_attributes'
Expand Down
File renamed without changes.
64 changes: 64 additions & 0 deletions code/pyqgis/solutions/exercise8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import os
import time

data_dir = os.path.join(os.path.expanduser('~'), 'Downloads', 'pyqgis_masterclass')

layer = iface.activeLayer()

# Check if a layer is selected
if not layer:
iface.messageBar().pushMessage('Please select a layer', level=Qgis.Critical)
# Check if the selected layer is a vector layer
if layer.type() != QgsMapLayer.VectorLayer:
iface.messageBar().pushMessage('Please select a vector layer', level=Qgis.Critical)

# Define parameters for QgsVectorFileWriter
output_name = 'output.csv'
output_path = os.path.join(data_dir, output_name)

# We will use QgsVectorFileWriter.create() method
# It takes the following parameters
# fileName: Path to the file
# fields: Fields to write
# geometryType: geometry type of output file
# srs: CRS of the output file
# transformContext: Datum transformation settings
# options: Save Options such as format, encoding etc.

# Define the options for saving the layer
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = 'CSV'
save_options.fileEncoding = 'UTF-8'
# We can also add some format-specific layer options
# These come from GDAL/OGR
# https://gdal.org/drivers/vector/csv.html
save_options.layerOptions = ['SEPARATOR=COMMA']

# Write the file
writer = QgsVectorFileWriter.create(
fileName=output_path,
fields=layer.fields(),
geometryType=QgsWkbTypes.NoGeometry,
srs=layer.crs(),
transformContext=transform_context,
options=save_options)

# Check if we were able to create the writer
if writer.hasError() != QgsVectorFileWriter.NoError:
iface.messageBar().pushMessage(
'Error:', writer.errorMessage, level=Qgis.Critical)

selected_count = layer.selectedFeatureCount()
if selected_count == 0:
iface.messageBar().pushMessage(
'Error:', 'No selected features', level=Qgis.Critical)
else:
for f in layer.selectedFeatures():
writer.addFeature(f)

# delete the writer to flush features to disk
del writer
iface.messageBar().pushMessage(
'Success:',
f'Output file with {selected_count} features written at {output_path}',
level=Qgis.Success)
11 changes: 1 addition & 10 deletions docs/code/pyqgis/save_attributes_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@
output_name = 'output.csv'
output_path = os.path.join(data_dir, output_name)

# We will use QgsVectorFileWriter.create() method
# It takes the following parameters
# fileName: Path to the file
# fields: Fields to write
# geometryType: geometry type of output file
# srs: CRS of the output file
# transformContext: Datum transformation settings
# options: Save Options such as format, encoding etc.

# Define the options for saving the layer
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = 'CSV'
Expand All @@ -40,7 +31,7 @@
fields=layer.fields(),
geometryType=QgsWkbTypes.NoGeometry,
srs=layer.crs(),
transformContext=transform_context,
transformContext=QgsProject.instance().transformContext(),
options=save_options)

# Check if we were able to create the writer
Expand Down
55 changes: 32 additions & 23 deletions docs/code/pyqgis/save_attributes_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,63 @@
from qgis.core import (QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterEnum,
QgsProcessingParameterFileDestination,
QgsWkbTypes)
QgsVectorFileWriter,
QgsWkbTypes,
QgsProject)


class SaveAttributesAlgorithm(QgsProcessingAlgorithm):
"""Saves the attributes of a vector layer to a CSV file."""
OUTPUT = 'OUTPUT'
INPUT = 'INPUT'

def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterFeatureSource(
self.INPUT,
self.tr('Input layer'),
'INPUT',
'Input layer',
[QgsProcessing.TypeVectorAnyGeometry]
)
)

# We add a file output of type CSV.
self.addParameter(
QgsProcessingParameterFileDestination(
self.OUTPUT,
self.tr('Output File'),
'OUTPUT',
'Output File',
'CSV files (*.csv)',
)
)

def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(
layer = self.parameterAsVectorLayer(
parameters,
self.INPUT,
'INPUT',
context)

sink, output = self.parameterAsSink(
parameters,
self.OUTPUT,
context,
source.fields(),
QgsWkbTypes.NoGeometry,
source.sourceCrs()
)

fieldnames = [field.name() for field in source.fields()]
output = self.parameterAsFileOutput(
parameters,
'OUTPUT',
context)

# Compute the number of steps to display within the progress bar and
# get features from source
total = 100.0 / source.featureCount() if source.featureCount() else 0
features = source.getFeatures()
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
features = layer.getFeatures()

# Define the options for saving the layer
save_options = QgsVectorFileWriter.SaveVectorOptions()
save_options.driverName = 'CSV'
save_options.fileEncoding = 'UTF-8'

# Create the writer
writer = QgsVectorFileWriter.create(
fileName=output,
fields=layer.fields(),
geometryType=QgsWkbTypes.NoGeometry,
srs=layer.crs(),
transformContext=QgsProject.instance().transformContext(),
options=save_options)


for current, f in enumerate(features):
Expand All @@ -58,12 +67,12 @@ def processAlgorithm(self, parameters, context, feedback):
break

# Add a feature in the sink
sink.addFeature(f)
writer.addFeature(f)

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

return {self.OUTPUT: output}
return {'OUTPUT': output}

def name(self):
return 'save_attributes'
Expand Down
35 changes: 35 additions & 0 deletions docs/code/pyqgis/solutions/exercise10.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
layer_id = '[%@layer_id%]'
fid = [% $id %]

layer = QgsProject.instance().mapLayer(layer_id)

def get_neighbors(fid):
f = layer.getFeature(fid)
# Use list comprehension to get all intersecting features
# You may also use touches() if your data is topologically correct
# Supply the bounding box to getFeatures() to use Spatial Index
neighbors = [
c.id()
for c in layer.getFeatures(f.geometry().boundingBox())
if c.geometry().intersects(f.geometry()) and c.id() != f.id()
]
return neighbors


first_degree_neighbors = get_neighbors(fid)

second_degree_neighbors = set()

for n in first_degree_neighbors:
neighbors = get_neighbors(n)
second_degree_neighbors.update(neighbors)

# Remove all first-degree neighbors from the set
second_degree_neighbors = second_degree_neighbors.difference(
set(first_degree_neighbors))

# Remove the feature itself from the set if it exists
second_degree_neighbors.discard(fid)

# Apply the selection
layer.selectByIds(list(second_degree_neighbors), QgsVectorLayer.AddToSelection)
Loading

0 comments on commit faf9da1

Please sign in to comment.