Question

Like the example from the PostGIS refractions. The query splits a circle with a line. The results are two polygons. Additionally it selects the distinct polygons (n) and calculates the area of each object.

WITH split AS
(SELECT 
    ST_Split(circle, line) AS geom,
    generate_series(1,100) AS n
FROM (
    SELECT 
        ST_MakeLine(ST_MakePoint(10, 10),ST_MakePoint(190, 190)) AS line,
        ST_Buffer(ST_GeomFromText('POINT(100 90)'), 50) AS circle) AS foo),
objects AS
(SELECT
    n,
    ST_GeometryN(split.geom,n) AS geom
FROM split
    WHERE n <= ST_NumGeometries(split.geom))

    SELECT
        n,
        ST_Area(objects.geom),
        geom
    FROM objects

The query returns two objects with different area values.

My question is how I can select the smallest one? The problem is that in some cases the n=1 geometry is the smaller one and for another polygon the n=2 geometry is the smaller one.

I tried this in my final query but it doesn't work. It returns no geometry.

CASE
    WHEN ST_Area(ST_GeometryN(objects.geom,1)) < ST_Area(ST_GeometryN(objects.geom,2)) 
        THEN ST_GeometryN(objects.geom,1)
    ELSE ST_GeometryN(objects.geom,2)
END

What I want is the smaller polygon after the split.

I thought the CASE WHEN clause could help here. So, it is more a PostgreSQL issue.

Was it helpful?

Solution

Keeping me busy with this issue I found the LEAST and GREATEST functions in the PostgreSQL documentation.

The following final query (after the subqueries in my question) works, even if this approach is maybe not the most elegant one. The clue is ordering the results with the LEAST value of the area.

...

SELECT
    objects.n,
    -- objects.geom,
    ST_Area(objects.geom) AS area
FROM objects, split
    WHERE split.n <= ST_NumGeometries(split.geom)
        ORDER BY LEAST(ST_Area(ST_GeometryN(objects.geom,split.n)))
        -- LIMIT 1

The result set for this is:

 n |       area       
---+------------------
 2 | 3199.62422930388
 1 | 4603.98865134125
 1 | 4603.98865134125
 2 | 3199.62422930388
(4 rows)

When I limit this query by 1 and include the geometry column (both commented out in the query above), I have always selected the smallest piece from the split.

Is there a way to avoid the limiting?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top