ST_ConcaveHull
What is ST_ConcaveHull?
ST_ConcaveHull is a PostGIS function that returns a possibly concave polygon containing all points of the input geometry. Unlike the convex hull, it can "dent inward" to hug the shape of a point cloud more tightly, making it useful for estimating the footprint of irregular data.
ST_ConcaveHull(geometry param_geom, float param_pctconvex, boolean param_allow_holes = false) → geometryparam_pctconvex is a value between 0 and 1: 1 produces the convex hull, 0 produces the tightest possible concave hull. Lower values produce more concave, more detailed hulls.
When would you use ST_ConcaveHull?
Use ST_ConcaveHull when you need a tight boundary around scattered points — delineating the footprint of a GPS cluster, the area of influence of a branch network, or the shape of a protest crowd from mobile-phone pings. It is typically a better visual summary than the convex hull when the point distribution is irregular.
1SELECT ST_ConcaveHull(ST_Collect(geom), 0.8) AS footprint
2FROM delivery_points
3WHERE region_id = 'NYC';FAQs
When should I use ST_ConcaveHull vs ST_ConvexHull?
Use ST_ConvexHull when you want the simplest enclosing shape and mathematical guarantees — it is deterministic, fast, and always convex. Use ST_ConcaveHull when the input has a non-convex distribution (an L-shaped point cluster, a river-shaped track) and you want the hull to reflect that shape. Concave hulls are slower and require a tuning parameter.
What does the target_percent parameter actually do?
It controls how tightly the hull wraps the input. A value of 1.0 returns the convex hull; lower values allow more concavity. In practice 0.8 to 0.9 works well for most point clouds — very low values (below 0.3) can produce self-intersecting or strangely thin polygons.
Why is ST_ConcaveHull slow on large inputs?
The algorithm builds a Delaunay triangulation and iteratively removes long edges, which is O(n log n) in the best case but degrades with vertex count. For inputs over a few hundred thousand points, consider sampling first with TABLESAMPLE or clustering with ST_ClusterDBSCAN and hulling each cluster separately.
Can the result have holes?
Yes, if you pass param_allow_holes = true. By default holes are filled in, but enabling holes lets the hull reflect "empty" regions inside the point distribution — useful for detecting areas with no coverage inside an otherwise dense cluster.