QGIS – How to Subset Shapefile Features Based on Another Shapefile’s Position

qgisselect-by-location

I have a shapefile with thousands of polygons and a shapefile with 28 polygons that completely overlay the first shapefile.
I'm trying to split the first shapefile features into 28 smaller shapefiles based on the location of polygons in the second shapefile.
Here's an image of the subject.

enter image description here

Manually, I select one (blue) polygon and then I use the "Select Within" plugin which allows selecting features considering if the centroid of polygons falls into the layer of reference. Then I export the selection into a separate file.
I'd like to do this process automatically generating X files for X features of the shapefile of reference.

Is there any way to do something like this?

I guess that something with python is possible, but I'm still not able to write a script.

Best Answer

In case the two layer do not exactly match, so that the polygons of the layer with the smaller polygons (lets call it p2) at the borders overlap with more than one of the larger polygons of the other layer (p1), you can use the centroid of the smaller polygons and get the $id of the larger polygon that it is within. Use field calculator to create an attribute field called within with this expression. Then proceed as in step 2 of the other solution:

array_get (
    overlay_nearest('p1', $id, limit:=-1),
    array_find( 
    array_foreach (
        overlay_nearest('p1', $id, limit:=-1),
        within (
            centroid ($geometry),
            geometry (
                get_feature_by_id (
                    'p1',
                    @element))))
        ,
        1))

As you can see (e.g. at the highlighted spot), small poygons that overlap with two of the larger polygons are assigned to the side where the centroid is within: enter image description here

Edit

Tested with the dataset you provided in the comment. To get proper results with this data, use this expression (apply it on the layer with the small polygons; the layer with the larger polygons should be named p1):

array_max(
    array_foreach (
        overlay_intersects('p1',$id),
        if (
            within (
                centroid ($geometry), 
                geometry (get_feature_by_id ('p1', @element))
            ),
            @element,
            ''
        )
    )
)

Then use Split vectort layer based on the field created in this way as explained in my other solution.

enter image description here

Related Question