---
name: v.fill.holes
description: Fill holes in areas by keeping only outer boundaries
keywords: [ vector, geometry, fill, exterior, ring, perimeter ]
---

# v.fill.holes

Fill holes in areas by keeping only outer boundaries

=== "Command line"

    **v.fill.holes**
    **input**=*name*
    [**layer**=*string*]
    [**cats**=*range*]
    [**where**=*sql_query*]
    **output**=*name*
    [**--overwrite**]
    [**--verbose**]
    [**--quiet**]
    [**--qq**]
    [**--ui**]

    Example:

    ```sh
    v.fill.holes input=name output=name
    ```

=== "Python (grass.tools)"

    *grass.tools.Tools.v_fill_holes*(**input**,
        **layer**=*"1"*,
        **cats**=*None*,
        **where**=*None*,
        **output**,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    tools = Tools()
    tools.v_fill_holes(input="name", output="name")
    ```

    This grass.tools API is experimental in version 8.5 and expected to be stable in version 8.6.

=== "Python (grass.script)"

    *grass.script.run_command*("***v.fill.holes***",
        **input**,
        **layer**=*"1"*,
        **cats**=*None*,
        **where**=*None*,
        **output**,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    gs.run_command("v.fill.holes", input="name", output="name")
    ```

## Parameters

=== "Command line"

    **input**=*name* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Or data source for direct OGR access  
    **layer**=*string*  
    &nbsp;&nbsp;&nbsp;&nbsp;Layer number or name  
    &nbsp;&nbsp;&nbsp;&nbsp;Vector features can have category values in different layers. This number determines which layer to use. When used with direct OGR access this is the layer name.  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *1*  
    **cats**=*range*  
    &nbsp;&nbsp;&nbsp;&nbsp;Category values  
    &nbsp;&nbsp;&nbsp;&nbsp;Example: 1,3,7-9,13  
    **where**=*sql_query*  
    &nbsp;&nbsp;&nbsp;&nbsp;WHERE conditions of SQL statement without 'where' keyword  
    &nbsp;&nbsp;&nbsp;&nbsp;Example: income &lt; 1000 and population &gt;= 10000  
    **output**=*name* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map  
    **--overwrite**  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    **--help**  
    &nbsp;&nbsp;&nbsp;&nbsp;Print usage summary  
    **--verbose**  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    **--quiet**  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    **--qq**  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    **--ui**  
    &nbsp;&nbsp;&nbsp;&nbsp;Force launching GUI dialog

=== "Python (grass.tools)"

    **input** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Or data source for direct OGR access  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, vector, *name*  
    **layer** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Layer number or name  
    &nbsp;&nbsp;&nbsp;&nbsp;Vector features can have category values in different layers. This number determines which layer to use. When used with direct OGR access this is the layer name.  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, layer  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *1*  
    **cats** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Category values  
    &nbsp;&nbsp;&nbsp;&nbsp;Example: 1,3,7-9,13  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, cats, *range*  
    **where** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;WHERE conditions of SQL statement without 'where' keyword  
    &nbsp;&nbsp;&nbsp;&nbsp;Example: income &lt; 1000 and population &gt;= 10000  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, sql_query, *sql_query*  
    **output** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, vector, *name*  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  

    Returns:

    **result** : grass.tools.support.ToolResult | None  
    If the tool produces text as standard output, a *ToolResult* object will be returned. Otherwise, `None` will be returned.

    Raises:

    *grass.tools.ToolError*: When the tool ended with an error.

=== "Python (grass.script)"

    **input** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Or data source for direct OGR access  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, vector, *name*  
    **layer** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Layer number or name  
    &nbsp;&nbsp;&nbsp;&nbsp;Vector features can have category values in different layers. This number determines which layer to use. When used with direct OGR access this is the layer name.  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, layer  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *1*  
    **cats** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Category values  
    &nbsp;&nbsp;&nbsp;&nbsp;Example: 1,3,7-9,13  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, cats, *range*  
    **where** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;WHERE conditions of SQL statement without 'where' keyword  
    &nbsp;&nbsp;&nbsp;&nbsp;Example: income &lt; 1000 and population &gt;= 10000  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, sql_query, *sql_query*  
    **output** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, vector, *name*  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*

## DESCRIPTION

*v.fill.holes* fills empty spaces inside areas, specifically it
preserves areas with centroids while areas without centroids, which
typically represent holes, are removed. *v.fill.holes* goes over all
areas in a vector map and it preserves only outer boundaries of each
area while removing inner boundaries which are considered holes. The
holes become part of the area which contained them. No boundaries of
these holes are preserved.

![Several areas, some with holes (left) and the same areas but with holes filled (right)](v_fill_holes_filled.png)  
*Figure: Holes inside areas are removed. (a) Original areas with holes
and (b) the same areas but with holes filled.*

In case areas have empty space in between them, i.e., there are holes in
the overall coverage, but not in the areas themselves, *v.fill.holes*
can't assign this empty space to either of these areas because it does
not know which area this empty space should belong to. If the space
needs to be filled, this can be resolved by merging the areas around the
empty space into one by dissolving their common boundaries. This turns
the empty space into a hole inside one single area which turns the
situation into a case of one area with a hole.

![Two areas with empty space in between (left), both areas merged (middle), and the empty space filled (right)](v_fill_holes_filled_with_dissolve.png)  
*Figure: Empty space in between two areas does not belong to either
area, so it is filled only after the boundaries between areas are
dissolved, i.e., areas merged into one. (a) Original areas with space in
between, (b) one area with a hole after dissolving the common boundary,
and (c) hole filled.*

### Topology

Strictly speaking, in the GRASS topological model, an area is a closed
boundary (or a series of connected closed boundaries) which may have a
centroid. If it has a centroid, it is rendered as a filled area in
displays and this is what is usually considered an area from the user
perspective. These are the areas where *v.fill.holes* preserves the
associated outer boundary (or boundaries). Other closed boundaries,
i.e., those without a centroid, are not carried over to the output. All
other features are removed including points and lines.

### Attributes

If a specific layer is selected, attributes for that layer are preserved
for the areas based on the category or categories associated with each
area. By default, layer number 1 is selected. In case there are
attribute tables associated with other layers or attributes associated
with categories of other features than areas with centroids, this
attribute data is not carried over to the output just like the
corresponding geometries.

## EXAMPLE

The *lakes* vector map in the North Carolina sample dataset represents
islands inside lakes as areas distinguished by attributes. To
demonstrate *v.fill.holes*, we will first extract only the lakes which
will create holes where the islands were located. Then, we will fill the
holes created in the lakes to get the whole perimeter of the lakes
including islands. Remove the islands by extracting everything else
(results in holes):

```sh
v.extract input=lakes where="FTYPE != 'ROCK/ISLAND'" output=lakes_only
```

Remove the holes:

```sh
v.fill.holes input=lakes_only output=lakes_filled
```

![Lake without holes overlapping with the lines marking the original](v_fill_holes.png)  
*Figure: The filled lake (blue) and borders of the original lakes with
islands removed (light blue). Figure shows a smaller area in the north
of the data extent.*

## SEE ALSO

- *[v.dissolve](v.dissolve.md)* for removing common boundaries based on
  attributes,
- *[v.clean](v.clean.md)* for removing topological issues,
- *[r.fillnulls](r.fillnulls.md)* for filling empty spaces in raster
  maps using interpolation,
- *[r.fill.stats](r.fill.stats.md)* for filling empty spaces in raster
  maps using statistics.

## AUTHOR

Vaclav Petras, [NCSU Center for Geospatial Analytics, GeoForAll
Lab](http://geospatial.ncsu.edu/)

## SOURCE CODE

Available at: [v.fill.holes source code](https://github.com/OSGeo/grass/tree/main/vector/v.fill.holes)
([history](https://github.com/OSGeo/grass/commits/main/vector/v.fill.holes))  
Latest change: Friday Jun 20 15:13:04 2025 in commit [9dd92f9](https://github.com/OSGeo/grass/commit/9dd92f956684722d9ad0ff5f3e724b92cb8e1a5b)
