# PostGIS - Get a point inside a line or polygon

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?

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

• For lines ST_LineInterpolatePoint with fraction 0.5 should be perfect postgis.net/docs/manual-2.1/ST_LineInterpolatePoint.html Commented May 10, 2016 at 18:42
• ST_PointOnSurface() works with Lines ! (thx Postgis)
– WKT
Commented 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. Commented 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 :

``````SELECT
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
``````
• && operator checks only bbox. You may want to use ST_intersects().
– WKT
Commented May 10, 2016 at 20:40
• You're right. I was wrong. I'll update my answer. Thanks! Commented 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

``````SELECT
CASE
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
``````