I use STPointOnSurface when I need an interior point rather than a particular coordinate formula. The returned point is arbitrary. I’d validate its relationship to the polygon instead of expecting one fixed location from every implementation.

Keep the hole in the source
The first polygon has an outer square and a smaller square hole. The second has no hole. The third is an empty polygon. Each source uses the same planar SRID, so the membership checks compare compatible values.
A hole is excluded from the polygon’s interior. A representative point must therefore be in the remaining region, not just somewhere inside the outer ring. I keep the original Shape available beside the generated point. That makes the required membership relationship explicit.
WITH Inputs AS
(
SELECT CaseId, Shape
FROM (VALUES
(1,geometry::STGeomFromText('POLYGON((0 0,6 0,6 6,0 6,0 0),(2 2,2 4,4 4,4 2,2 2))',0)),
(2,geometry::STGeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))',0)),
(3,geometry::STGeomFromText('POLYGON EMPTY',0))
) v(CaseId,Shape)
), Chosen AS
(
SELECT CaseId, Shape, Shape.STPointOnSurface() AS InteriorPoint FROM Inputs
)
SELECT CaseId, Shape.STIsEmpty() AS SourceIsEmpty,
CAST(InteriorPoint.STGeometryType() AS nvarchar(40)) AS ChosenType,
Shape.STContains(InteriorPoint) AS SourceContainsChosen,
CAST(CASE WHEN InteriorPoint IS NULL THEN 1 ELSE 0 END AS bit) AS ChosenIsNull
FROM Chosen
ORDER BY CaseId;

Validate the point’s relationship
For each nonempty polygon, the expected chosen type is Point. SourceContainsChosen is true, and ChosenIsNull is false. Those properties capture the useful contract without guessing a specific x or y value.

I’d avoid storing an analytically invented coordinate in an expected-result table. The returned point is arbitrary, so one valid point doesn’t define every possible result. A consumer needing repeatable placement must establish that requirement separately. Interior membership alone doesn’t promise a preferred label position.
Read the empty case separately
The empty polygon expects a NULL chosen value. There is no Point type or membership result to report for that missing selection. ChosenIsNull makes the state visible without replacing it with an origin point.
Zero, zero is a real coordinate, not a universal missing-value marker. Substituting it could accidentally place a feature somewhere meaningful. I’d handle an empty region as a separate presentation state. The lack of a selected point is part of the result contract.
Avoid inferring a central location
The method name doesn’t guarantee the visually central point or a business-specific meeting location. Its purpose here is to return an interior point. Those are different requirements, especially for irregular shapes and polygons with excluded holes.
I’d explain the chosen property before using it in an application. A valid interior point can still be unsuitable for a label near an obstruction. Placement rules may include clearance, visibility or another constraint. This read-only example doesn’t invent those additional policies.
Keep the returned value available
The derived point remains a geometry value in the Chosen CTE. The output projects only properties needed for the check. A later application could keep the geometry itself instead of reducing it to a text coordinate immediately.
I’d preserve the spatial type while making further compatible comparisons. Formatting a point for display is a separate step. Losing that type can make a later consumer guess coordinate order or reference system. The small property table should explain behavior, not replace the underlying spatial contract.
Review complete states during validation
The three rows are explicitly ordered by CaseId. The query creates no objects and changes no data. Every returned column belongs to the expected comparison, including NULL membership in the empty case.
I’d test actual application inputs separately before relying on this selection. A valid sample doesn’t prove a production source is valid or uses the intended SRID. Keep source validation, point selection and business placement as distinct decisions. Each stage needs evidence for its own requirement.
Check that the point is inside the region, and treat an empty shape as no point at all.
An interior point is not a central point, it is any location inside the region.
Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.
Discover more from SQL Authority with Pinal Dave
Subscribe to get the latest posts sent to your email.




