This blog posts tells how to do it with SQL in PostGIS http://geospatial.commons.gc.cuny.edu/2013/11/04/filling-in-holes-with-postgis/
Spatialite has also ExteriorRing function http://www.gaia-gis.it/gaia-sins/spatialite-sql-latest.html so you do not need to have PostGIS installed. Is it necessary for you to do the job with python inside QGIS? The SQL looks like this:
UPDATE my_spatial_table t
SET geom = a.geom
FROM (
SELECT gid, ST_Collect(ST_MakePolygon(geom)) AS geom
FROM (
SELECT gid, ST_NRings(geom) AS nrings,
ST_ExteriorRing((ST_Dump(geom)).geom) AS geom
FROM my_spatial_table
WHERE ST_NRings(geom) > 1
) s
GROUP BY gid, nrings
HAVING nrings > COUNT(gid)
) a
WHERE t.gid = a.gid;
Since you put GRASS into the tags, here's a solution based on GRASS:
First, you need to know exactly what coordinate system the original data is in (as always with GRASS). I see that the *.prj file contains "TRANSVERSE MERCATOR" but it's not one of the standard UTM zones. Since you have not mentioned the EPSG code of this data, here's the proj4 string for creating a new matching GRASS Location:
+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=WGS84 +units=m +no_defs
Now start GRASS, create a LOCATION (based on the above) and a MAPSET.
And now import the shapefile into GRASS by running:
v.in.ogr input="sp_data.shp" output=sp_data
Add a column for the area of each feature, and calculate its area:
v.db.addcolumn map=sp_data columns="area_sqm INT"
v.to.db sp_data option=area column=area_sqm unit=meters
Now convert to raster, using the area_sqm column as the raster value.
But first set the GRASS computational region:
g.region -p vector=sp_data res=100
Now create a vector grid of polygons at the raster resolution:
v.mkgrid map=grid
Intersect with the forest polygons, and calculate areas of these intersect polygons:
Intersect with the forest polygons, dissolve the polygons inside the same grid cell, calculate areas of these intersect polygons, and move the area value to the grid cells:
v.overlay ain=grid bin=sp_data operator=and output=forest_grid_intersect
v.dissolve --overwrite input=forest_grid_intersect@jn column=a_cat output=forest_grid_intersect_dissolve
v.db.addtable map=forest_grid_intersect_dissolve columns="area_sqm INT"
v.to.db forest_grid_intersect_dissolve option=area column=area_sqm unit=meters
v.db.join map=grid@jn column=cat other_table=forest_grid_intersect_dissolve other_column=cat
v.db.addcolumn map=forest_grid_intersect columns="area_sqm INT"
v.to.db forest_grid_intersect option=area column=area_sqm unit=meters
and convert to raster, using the area attribute as the raster value:
v.to.rast input=grid type=area output=sp_data_rast use=attr attribute_column=area_sqm
And you're done. Hope I have it right this time :-) .
Best Answer
There might be simpler way of solving this problem by using some library, but one possible way with only Turf.js would be to:
Code could then look something like this:
Result then looks like this:
EDIT: When testing again with GeoJSON with several holes, turf.js complained executing
var coords = turf.getCoords(polygon)
, so I had to change logic a bit.Here is modified code:
And here the result: