10

I have a polygon layer with multiple polygon features drawn on it.

I need a tool that will draw a bounding box around each polygon feature individually. Right now everything I try in the tool box draws a single bounding box that encompasses all the polygon features. Is there such a tool?

Taras
  • 32,823
  • 4
  • 66
  • 137
bkg73123
  • 165
  • 1
  • 1
  • 7
  • 1
    @BERA You nailed it! (Please see bkg73123's comment to Cushen) – Kazuhito Jul 04 '18 at 14:49
  • Thank you so much! I was using the Bounding Box tool but it was giving me one big box. The iterate function didn't do it either. I had to do the multipart to singlepart tool first and then run the Bounding Box tool without iterate to get the results I needed. NOW I am trying to take the Bounding Boxes it created and Buffer them, but I need them to Buffer like they would a Line with the Flat end cap style. Should I create a new thread for this question or continue it here? When I try and buffer the bounding boxes it buffers them in all direction even if I select Flat end cap style. Thank you! – – bkg73123 Jul 04 '18 at 19:12

6 Answers6

19

In the Processing Toolbox (Processing Tab > Toolbox or Ctrl+Alt+T) you will find a tool called Bounding boxes. This will achieve what you want.

enter image description here

If your layer contains some multipart features you might want to run the Multipart to singleparts first (Depending on what output you want.)

Input > Output: enter image description here

Taras
  • 32,823
  • 4
  • 66
  • 137
Cushen
  • 2,928
  • 13
  • 15
  • You need to use the iterate tool (click on the green arrow) to get a bounding box for each polygon. – ahmadhanb Jul 04 '18 at 06:07
  • 1
    Are you sure? I'm running QGIS version 3.0.0-Girona and that is not the case, this tool creates a bounding box for each feature in an input layer. – Cushen Jul 04 '18 at 06:10
  • If the OP needs a separate feature for each bounding box, then clicking on the green arrow will give what he wants. – ahmadhanb Jul 04 '18 at 06:17
  • 1
    That is what the tool does, please try it locally, I have tested it. – Cushen Jul 04 '18 at 06:27
  • https://gis.stackexchange.com/questions/75332/what-does-feature-mean-in-qgis – Cushen Jul 04 '18 at 06:57
  • 1
    Thank you so much! I was using the Bounding Box tool but it was giving me one big box. The iterate function didn't do it either. I had to do the multipart to singlepart tool first and then run the Bounding Box tool without iterate to get the results I needed. NOW I am trying to take the Bounding Boxes it created and Buffer them, but I need them to Buffer like they would a Line with the Flat end cap style. Should I create a new thread for this question or continue it here? When I try and buffer the bounding boxes it buffers them in all direction even if I select Flat end cap style. Thank you! – bkg73123 Jul 04 '18 at 13:33
  • Great, glad that worked for you, if you are happy you can accept the answer, click green tick. That other question would be best as another thread, as I'm not quite sure what you mean. – Cushen Jul 04 '18 at 23:12
7

If you want to have a separate feature class for each bounding box, you need to use the iterate tool (click on the green arrow) to get a bounding box for each polygon.

enter image description here

Without using the iterator, you will get all bounding boxes in one fearture class:

enter image description here

But using the iterator (the green arrow) will produce a bounding box for each polygon individually as a new feature class:

enter image description here

ahmadhanb
  • 40,826
  • 5
  • 51
  • 105
3

There is a possibility using a "Virtual Layer" through Layer > Add Layer > Add/Edit Virtual Layer...

Let's assume there is a polygon layer called 'test' with its corresponding attribute tables, see image below.

input

With the following query, it is possible to get the bounding box for each feature in the source layer.

SELECT id,
       ST_Envelope(geometry) AS geom,
       ST_AsText(ST_Envelope(geometry)) AS geom_text,
       -- XMIN,YMIN,XMAX,YMAX
       x_min(ST_Envelope(geometry)) || ',' ||
       y_min(ST_Envelope(geometry)) || ',' ||
       x_max(ST_Envelope(geometry)) || ',' ||
       y_max(ST_Envelope(geometry)) AS bbox
FROM "test"

The output polygon layer (grey) with its attribute table will look like

result

Taras
  • 32,823
  • 4
  • 66
  • 137
3

Here is a solution using python

def boundingbox(shp_dir, out_dir, obj_file, epsg='4326'):
    save_name = 0
    obj = glob.glob(obj_file + '/*.shp')[0]
    df = gpd.read_file(obj)
    # iterrate through verticies to find min and max of y and x
    for vertex in df.geometry:
        x, y = vertex.exterior.coords.xy
        xmin = min(x)
        xmax = max(x)
        ymin = min(y)
        ymax = max(y)
    # Create rectangle points
    upper_left = (xmin, ymax)
    upper_right = (xmax, ymax)
    lower_left = (xmin, ymin)
    lower_right = (xmax, ymin)

    # save shapefile containing one bounding box shape
    w = shapefile.Writer(shp_dir + str(save_name) + '.shp')
    w.field("name", "C")  # pyshp needs at least one field
    w.poly([[lower_left, lower_right, upper_right, upper_left]])  # generate bbox polygon
    w.record('bbox')
    w.close()

    # generate .PRJ file
    crs_wkt = 'epsg: ' + epsg
    prj = open(shp_dir + str(save_name) + '.prj', "w")
    prj.write(crs_wkt)
    prj.close()

    save_name = save_name + 1

shapefiles = glob.glob(shp_dir + '/' + '/*.shp')
gdf = pandas.concat([
    gpd.read_file(shp)
    for shp in shapefiles
]).pipe(gpd.GeoDataFrame)
gdf.crs = ('epsg:4326')
gdf.to_file(out_dir + '/' + 'merged.shp')

Binx
  • 1,350
  • 1
  • 9
  • 35
3

Here is a basic PyQGIS solution without external libraries:

layer = iface.activeLayer()
newlayer = QgsVectorLayer("Polygon?crs={}&index=yes".format(layer.crs().authid()), "BoundingBoxes", "memory")

with edit(newlayer): newlayer.dataProvider().addAttributes(layer.fields()) # copy the fields to the outputlayer newlayer.updateFields() # save the changes for feat in layer.getFeatures(): # iterate over inputlayer bbox = feat.geometry().boundingBox() # get the Boundingbox as QgsRectangle bbox_geom = QgsGeometry.fromRect(bbox) # Turn the QgsRectangle into QgsGeometry outfeat = QgsFeature() # Create a new feature outfeat.setAttributes(feat.attributes()) # copy the attributes to the outputlayer outfeat.setGeometry(bbox_geom) # set the geometry of the outputfeature to the bbox of the inputfeature newlayer.dataProvider().addFeature(outfeat) # add the feature to the outputlayer

QgsProject.instance().addMapLayer(newlayer)

It copies the features from the inputlayer 1 to 1 with all attributes and uses the inputfeatures boundingbox as geometry.

MrXsquared
  • 34,292
  • 21
  • 67
  • 117
2

To add a solution using QGIS expressions with Geometry generator or Geometry by expression (see here for differences) - use this expression:

bounds ($geometry)

Initial polygons in orange, boundin boxes created with geometry generator in blue: enter image description here

Babel
  • 71,072
  • 14
  • 78
  • 208