Centroid of a polygon is not always at the surface of that polygon. Consider the following example.
SELECT
"PolygonWithInnerRing".ST_asSVG() AS "SVG",
"PolygonWithInnerRing".ST_Centroid().ST_asSVG() AS "CENTROID_SVG"
FROM (
SELECT NEW ST_Polygon('Polygon ((-5 -5, 5 -5, 0 5, -5 -5), (-2 -2, -2 0, 2 0, 2 -2, -2 -2))') as "PolygonWithInnerRing"
FROM "DUMMY"
);
Slightly modified SVG for better visualization, like the one below:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.01 -5.01 10.02 10.02">
<path fill="yellow" stroke="black" stroke-width="0.1%" d="
M -5,5 l 10,0 -5,-10 Z
M -2,2 l 0,-2 4,0 0,2 Z
"/>
<rect width="1%" height="1%" stroke="red" stroke-width="1%" x="0" y="1.79365"/>
</svg>
shows that the centroid (the red dot) is located inside of the inner ring, and therefore not f the surface of the polygon.
In some cases you will need to have a point (like some sort of marker on the map) that lays somewhere on the surface of a given polygon. That’s the purpose of a method ST_PointOnSurface()
.
Update the example above to include the calculation of the point-on-surface.
SELECT
"PolygonWithInnerRing".ST_asSVG() AS "SVG",
"PolygonWithInnerRing".ST_PointOnSurface().ST_asSVG() AS "CENTROID_SVG"
FROM (
SELECT NEW ST_Polygon('Polygon ((-5 -5, 5 -5, 0 5, -5 -5), (-2 -2, -2 0, 2 0, 2 -2, -2 -2))') as "PolygonWithInnerRing"
FROM "DUMMY"
);
Again slightly modify styling of SVG objects, to have the centroid in red and the point-on-surface in blue.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.01 -5.01 10.02 10.02">
<path fill="yellow" stroke="black" stroke-width="0.1%" d="
M -5,5 l 10,0 -5,-10 Z
M -2,2 l 0,-2 4,0 0,2 Z
"/>
<rect width="1%" height="1%" stroke="red" stroke-width="1%" x="0" y="1.79365"/>
<rect width="1%" height="1%" stroke="blue" stroke-width="1%" x="-2.25" y="0"/>
</svg>
You can see on the visualization that the blue dot is indeed located on the yellow surface.