diff --git a/src/qgis_gender_indicator_tool/jobs/create_grids.py b/src/qgis_gender_indicator_tool/jobs/create_grids.py index 8c782b8b..c65fc873 100644 --- a/src/qgis_gender_indicator_tool/jobs/create_grids.py +++ b/src/qgis_gender_indicator_tool/jobs/create_grids.py @@ -32,100 +32,100 @@ def create_grids(self, layer, output_dir, crs, merged_output_path): if os.path.exists(merged_output_path): print(f"Merged grid already exists: {merged_output_path}") return merged_output_path - - layer = QgsVectorLayer(layer, "country_layer", "ogr") - if not layer.isValid(): - raise ValueError("Invalid country layer") - - # Reproject the country layer if necessary - if layer.crs() != crs: - layer = processing.run( - "native:reprojectlayer", - { - "INPUT": layer, - "TARGET_CRS": crs, - "OUTPUT": "memory:", - }, - feedback=QgsProcessingFeedback(), - )["OUTPUT"] - - all_grids = [] - - # Loop through each feature in the polygon layer - for feature in layer.getFeatures(): - geom = feature.geometry() - - # Check if the geometry is multipart - if geom.isMultipart(): - parts = ( - geom.asGeometryCollection() - ) # Separate multipart geometry into parts - else: - parts = [geom] # Single part geometry - - # Loop through each part of the geometry - for part_id, part in enumerate(parts): - part_area = part.area() - - # Get the extent of each part - part_extent = part.boundingBox() - - # Define the output grid path for each part - grid_output_path = ( - f"{output_dir}/grid_{feature.id()}_part_{part_id}.gpkg" - ) - - # Check if the grid already exists - if os.path.exists(grid_output_path): - print(f"Grid file already exists: {grid_output_path}") - grid_layer = QgsVectorLayer( - grid_output_path, "grid_layer", "ogr" - ) # Load the existing grid layer - # Clip the grid to the polygon feature (to restrict it to the boundaries) - clipped_grid_output_path = ( - f"{output_dir}/clipped_grid_{feature.id()}_part_{part_id}.gpkg" - ) - clip_params = { - "INPUT": grid_layer, # The grid we just created - "OVERLAY": layer, # The layer we're clipping to - "OUTPUT": clipped_grid_output_path, - } - clip_result = processing.run("native:clip", clip_params) - grid_layer = clip_result["OUTPUT"] # The clipped grid + else: + layer = QgsVectorLayer(layer, "country_layer", "ogr") + if not layer.isValid(): + raise ValueError("Invalid country layer") + + # Reproject the country layer if necessary + if layer.crs() != crs: + layer = processing.run( + "native:reprojectlayer", + { + "INPUT": layer, + "TARGET_CRS": crs, + "OUTPUT": "memory:", + }, + feedback=QgsProcessingFeedback(), + )["OUTPUT"] + + all_grids = [] + + # Loop through each feature in the polygon layer + for feature in layer.getFeatures(): + geom = feature.geometry() + + # Check if the geometry is multipart + if geom.isMultipart(): + parts = ( + geom.asGeometryCollection() + ) # Separate multipart geometry into parts else: - print(f"Creating grid: {grid_output_path}") - # Define grid creation parameters - grid_params = { - "TYPE": 2, # Rectangle (polygon) - "EXTENT": part_extent, # Use the extent of the current part - "HSPACING": self.h_spacing, # Horizontal spacing - "VSPACING": self.v_spacing, # Vertical spacing - "CRS": crs, # Coordinate reference system (CRS) - "OUTPUT": grid_output_path, # Output path for the grid file - } - - # Create the grid using QGIS processing - grid_result = processing.run("native:creategrid", grid_params) - grid_layer = grid_result["OUTPUT"] # Get the grid layer - - # Clip the grid to the polygon feature (to restrict it to the boundaries) - clipped_grid_output_path = ( - f"{output_dir}/clipped_grid_{feature.id()}_part_{part_id}.gpkg" + parts = [geom] # Single part geometry + + # Loop through each part of the geometry + for part_id, part in enumerate(parts): + part_area = part.area() + + # Get the extent of each part + part_extent = part.boundingBox() + + # Define the output grid path for each part + grid_output_path = ( + f"{output_dir}/grid_{feature.id()}_part_{part_id}.shp" ) - clip_params = { - "INPUT": grid_layer, # The grid we just created - "OVERLAY": layer, # The layer we're clipping to - "OUTPUT": clipped_grid_output_path, - } - clip_result = processing.run("native:clip", clip_params) - grid_layer = clip_result["OUTPUT"] # The clipped grid - - # Add the generated or loaded grid to the list - all_grids.append(grid_layer) - - # Merge all grids into a single layer - print(f"Merging grids into: {merged_output_path}") - merge_params = {"LAYERS": all_grids, "CRS": crs, "OUTPUT": merged_output_path} - merged_grid = processing.run("native:mergevectorlayers", merge_params)["OUTPUT"] - - return merged_grid + + # Check if the grid already exists + if os.path.exists(grid_output_path): + print(f"Grid file already exists: {grid_output_path}") + grid_layer = QgsVectorLayer( + grid_output_path, "grid_layer", "ogr" + ) # Load the existing grid layer + # Clip the grid to the polygon feature (to restrict it to the boundaries) + clipped_grid_output_path = ( + f"{output_dir}/clipped_grid_{feature.id()}_part_{part_id}.shp" + ) + clip_params = { + "INPUT": grid_layer, # The grid we just created + "OVERLAY": layer, # The layer we're clipping to + "OUTPUT": clipped_grid_output_path, + } + clip_result = processing.run("native:clip", clip_params) + grid_layer = clip_result["OUTPUT"] # The clipped grid + else: + print(f"Creating grid: {grid_output_path}") + # Define grid creation parameters + grid_params = { + "TYPE": 2, # Rectangle (polygon) + "EXTENT": part_extent, # Use the extent of the current part + "HSPACING": self.h_spacing, # Horizontal spacing + "VSPACING": self.v_spacing, # Vertical spacing + "CRS": crs, # Coordinate reference system (CRS) + "OUTPUT": grid_output_path, # Output path for the grid file + } + + # Create the grid using QGIS processing + grid_result = processing.run("native:creategrid", grid_params) + grid_layer = grid_result["OUTPUT"] # Get the grid layer + + # Clip the grid to the polygon feature (to restrict it to the boundaries) + clipped_grid_output_path = ( + f"{output_dir}/clipped_grid_{feature.id()}_part_{part_id}.shp" + ) + clip_params = { + "INPUT": grid_layer, # The grid we just created + "OVERLAY": layer, # The layer we're clipping to + "OUTPUT": clipped_grid_output_path, + } + clip_result = processing.run("native:clip", clip_params) + grid_layer = clip_result["OUTPUT"] # The clipped grid + + # Add the generated or loaded grid to the list + all_grids.append(grid_layer) + + # Merge all grids into a single layer + print(f"Merging grids into: {merged_output_path}") + merge_params = {"LAYERS": all_grids, "CRS": crs, "OUTPUT": merged_output_path} + merged_grid = processing.run("native:mergevectorlayers", merge_params)["OUTPUT"] + + return merged_grid diff --git a/src/qgis_gender_indicator_tool/jobs/points_per_grid_cell.py b/src/qgis_gender_indicator_tool/jobs/points_per_grid_cell.py index 589dc2b1..4211cd32 100644 --- a/src/qgis_gender_indicator_tool/jobs/points_per_grid_cell.py +++ b/src/qgis_gender_indicator_tool/jobs/points_per_grid_cell.py @@ -34,7 +34,9 @@ def raster_point_grid_score(self): self.v_spacing = 100 create_grid = GridCreator(h_spacing=self.h_spacing, v_spacing=self.v_spacing) output_dir = os.path.join("output") - merged_output_path = os.path.join(output_dir, "merged_grid.gpkg") + merged_output_path = os.path.join(output_dir, "merged_grid.shp") # Use Shapefile + + # Create grid layer using Shapefile grid_layer = create_grid.create_grids( self.country_boundary, output_dir, self.crs, merged_output_path ) @@ -79,7 +81,7 @@ def raster_point_grid_score(self): reclass_vals[grid_feat.id()] = reclass_val - # Step 5: Apply the score values to the grid + # Apply the score values to the grid grid_layer.startEditing() for grid_feat in grid_layer.getFeatures(): grid_layer.changeAttributeValue( @@ -89,9 +91,12 @@ def raster_point_grid_score(self): ) grid_layer.commitChanges() + merged_output_vector = os.path.join(output_dir, "merged_grid_vector.shp") # Use Shapefile for merged output + + # Merge grids into a single Shapefile layer Merge = processing.run( "native:mergevectorlayers", - {"LAYERS": [grid_layer], "CRS": None, "OUTPUT": "memory:"}, + {"LAYERS": [grid_layer], "CRS": None, "OUTPUT": 'memory:'}, ) merge = Merge["OUTPUT"] diff --git a/test/test_create_grids.py b/test/test_create_grids.py index 292da079..1d4005a6 100644 --- a/test/test_create_grids.py +++ b/test/test_create_grids.py @@ -22,7 +22,7 @@ def test_create_grids(self): os.path.dirname(__file__), "test_data/admin/Admin0.shp" ) self.output_dir = os.path.join(os.path.dirname(__file__), "output") - self.merged_output_path = os.path.join(self.output_dir, "merged_grid.gpkg") + self.merged_output_path = os.path.join(self.output_dir, "merged_grid.shp") self.utm_crs = QgsCoordinateReferenceSystem("EPSG:32620") # UTM Zone 20N self.h_spacing = 100 self.v_spacing = 100