I need to get the center point of a line or polygon to make marker for my app. So that when you click a marker the geometry appears (line or polygon). I used ST_Centroid to make it work.

The result is what I expected unnest some polygons or lines whichs centroids are out of the geometry. What i would like for those lines or polygons is to get the "most center point" but inside the geometry.

How can I do this? Is there a solution?

3 Answers 3


From the doc: ST_PointOnSurface — Returns a POINT guaranteed to lie on the surface.

  • 4
    For lines ST_LineInterpolatePoint with fraction 0.5 should be perfect postgis.net/docs/manual-2.1/ST_LineInterpolatePoint.html
    – user30184
    May 10, 2016 at 18:42
  • ST_PointOnSurface() works with Lines ! (thx Postgis)
    – WKT
    May 10, 2016 at 19:09
  • Yes! You're right @user30184 because it seems that for lines ST_PointOnSurface() takes a point arbitrary, i'm not sure but in doc example takes the first point of a LineString. May 10, 2016 at 19:54

In my case I have each geometry in disctint tables. What I did was :

  1. For lines -> ST_LineInterpolatePoint() with 0.5 factor.
  2. For polygons -> Test if ST_Centroid() is inside its geometry. If so, ST_Centroid() is the best choice, if not I choose PointOnSurface().

Here's the query :

    CASE WHEN (SELECT the_geom FROM points WHERE gid = d.gid) IS NOT NULL
    THEN (SELECT the_geom FROM points WHERE gid = d.gid)
    WHEN (SELECT the_geom FROM lines WHERE gid = d.gid) IS NOT NULL
    THEN ST_LineInterpolatePoint((SELECT the_geom FROM lines WHERE gid = d.gid), 0.5)
    WHEN (SELECT the_geom FROM polygons WHERE gid = d.gid AND ST_Intersects(ST_Centroid(the_geom),the_geom)) IS NOT NULL
    THEN ST_Centroid((SELECT the_geom FROM polygons WHERE gid = d.gid))
    ELSE ST_PointOnSurface((SELECT the_geom FROM polygons WHERE gid = d.gid))
    END AS center
FROM someTable d
  • 5
    && operator checks only bbox. You may want to use ST_intersects().
    – WKT
    May 10, 2016 at 20:40
  • You're right. I was wrong. I'll update my answer. Thanks! May 10, 2016 at 20:44

In the @Jose 's answer, instead of intersect we should use contains and in when condition we should use Boolean validation

       WHEN (ST_Contains(the_geom, ST_Centroid(the_geom))) IS TRUE
       THEN ST_Centroid(the_geom)
       ELSE ST_PointOnSurface(the_geom)
    END AS center
FROM someTable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.