Dear Open Foris team,

I am trying to calculate the Land Productivity Dynamics with Earth Map using a complex polygon to be found in this folder: https://drive.google.com/drive/folders/1ITQTTHS2w4tVwZseIJurv0Ov5TNupQte The polygon has been generated following a river stream with a buffer of 12 km.

What do you suggest, shall I simplify it to perform the analytics?

asked 13 Sep, 11:34

carmen_morales's gravatar image

carmen_morales
113
accept rate: 0%

edited 14 Sep, 14:18

Open%20Foris's gravatar image

Open Foris ♦♦
9995714


Problem:

The issue you're encountering while calculating analytics on Earth Map is not so much about the size of the area of your shapefile, but more about the complexity of the polygons themselves. Google Earth Engine, which Earth Map depends on, struggles with very complex polygons, particularly when there is clipping involved. This is compounded when the shapefile contains many small polygons and holes.

For example, the shapefile you're using includes many small islands in the rivers and holes (such as small lakes) outside the rivers.

Zoomed detail showing islands and holes:
Detail of islands and holes

These small polygons and holes cause performance issues during analysis. The best solution is to simplify the shapefile by removing them. You can do this using a tool like QGIS or with a simple Python script, which I'll guide you through below.


Solution: Simplify Your Shapefile with Python

Here’s how you can clean up your shapefile by removing small polygons (less than 100 hectares by default) and holes within polygons. This will make the shapefile easier to process on Earth Map and Google Earth Engine.

Steps:

  1. Install Python (if you don’t already have it).
  2. Run this command to install the necessary libraries: pip install geopandas
  3. Copy the code below into a file named preparePolygon.py.
  4. Run the script with: python preparePolygon.py

Important Notes: - Change the shapefile path to your file's location in line 29. - Check the CRS (Coordinate Reference System) for your area and adjust it in line 33. If you're unsure, feel free to ask on the forum. - You can modify the minimum polygon size (default is 100 hectares) in line 45. - The script outputs both a shapefile and a GeoJSON file. The GeoJSON can be used directly in Earth Map!

You can download the Python Script here


Python Script to Simplify Polygons:

import geopandas as gpd
from shapely.geometry import Polygon, MultiPolygon

# Function to remove holes from a polygon or multipolygon
def remove_holes(geometry):
    if isinstance(geometry, Polygon):
        return Polygon(geometry.exterior)  # Keep only the exterior (no holes)
    elif isinstance(geometry, MultiPolygon):
        return MultiPolygon([Polygon(p.exterior) for p in geometry.geoms])
    else:
        return geometry

# Function to round the coordinates of a polygon or multipolygon to a specific precision
def round_coordinates(geometry, precision=6):
    if isinstance(geometry, Polygon):
        exterior_rounded = [(round(x, precision), round(y, precision)) for x, y in geometry.exterior.coords]
        return Polygon(exterior_rounded)
    elif isinstance(geometry, MultiPolygon):
        return MultiPolygon([round_coordinates(p, precision) for p in geometry.geoms])
    else:
        return geometry

# Load your shapefile
shapefile_path = 'C:/Temp/Nigeria_StudyArea_EarthMap/Nigeria_StudyArea.shp'
gdf = gpd.read_file(shapefile_path)

# Reproject to UTM zone 31N (EPSG: 32631) for western Nigeria
gdf_projected = gdf.to_crs(epsg=32631)

# Remove holes from all geometries
gdf_projected['geometry'] = gdf_projected['geometry'].apply(remove_holes)

# Explode multipolygons into individual polygons for area filtering
gdf_exploded = gdf_projected.explode(index_parts=False)

# Calculate area in hectares (since UTM CRS is in meters)
gdf_exploded['area_ha'] = gdf_exploded.geometry.area / 10000  # Convert square meters to hectares

# Filter out polygons smaller than 100 hectares
gdf_filtered = gdf_exploded[gdf_exploded['area_ha'] >= 100]

# Group polygons back into multipolygons where necessary
gdf_final = gdf_filtered.dissolve(by=gdf_filtered.index)

# Reproject the final GeoDataFrame to EPSG:4326 (WGS84)
gdf_final = gdf_final.to_crs(epsg=4326)

# Round the geometry coordinates to 6 decimal places
gdf_final['geometry'] = gdf_final['geometry'].apply(lambda geom: round_coordinates(geom, precision=6))

# Save the filtered shapefile
shapefile_output = 'shapefileWithNoHolesOrSmallPolygons.shp'
gdf_final.to_file(shapefile_output)

# Save the filtered GeoDataFrame as a GeoJSON
geojson_output = 'shapefileWithNoHolesOrSmallPolygons.geojson'
gdf_final.to_file(geojson_output, driver='GeoJSON')

print(f"Filtered shapefile saved to: {shapefile_output}")
print(f"Filtered GeoJSON saved to: {geojson_output}")

Output Files:

  • Shapefile: shapefileWithNoHolesOrSmallPolygons.shp
  • GeoJSON: shapefileWithNoHolesOrSmallPolygons.geojson

You can now upload the cleaned GeoJSON directly into Earth Map for better performance.

Let us know if this solution works for you! We’ve tested it on your shapefile, and here are the results:

Result

permanent link

answered 13 Sep, 13:59

Open%20Foris's gravatar image

Open Foris ♦♦
9995714
accept rate: 10%

edited 13 Sep, 14:02

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×18

question asked: 13 Sep, 11:34

question was seen: 87 times

last updated: 14 Sep, 14:18