How the ST_Contains Geometry Checker works, and what it assumes
ST_Contains(A, B) asks the ST_Within question with the arguments the other way round: it is true when no point of B lies outside A and the interiors of A and B share at least one point. In DE-9IM terms the pattern is T*****FF*, read from the intersection matrix the engine computes for the pair, and the matrix is displayed so you can compare it with ST_Relate in your own database.
Argument order is the commonest mistake with ST_Contains in a spatial join. The containing geometry, usually the polygon, goes first: ST_Contains(region.geom, site.geom). Swap A and B on this page to see the reverse question answered, and the verdict change.
A polygon does not contain the points of its own boundary. A point exactly on an edge touches the polygon instead, and ST_Covers is the PostGIS function that counts it. Collections are handled deliberately rather than silently: a FeatureCollection of points is tested as one MultiPoint, so ST_Contains is only true when every one of them is inside A. The page says whenever it has combined features like this.
Where this comes up in GIS work
- Writing a spatial join that assigns customers, assets or incidents to the region that contains them.
- Checking that every building footprint sits inside its land parcel.
- Finding out why a containment check fails for a point that lies exactly on a boundary.
- Confirming the argument order of a query, which is the commonest ST_Contains bug.
A worked example
A square and a point well inside it:
A: POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))
B: POINT (4 6)
ST_Contains(A, B) = true
DE-9IM matrix: 0F2FF1FF2
Move the point onto the right-hand edge, POINT (10 5), and the answer becomes false. The matrix FF20F1FF2 shows why: the point now meets the polygon's boundary (the 0 in the middle row) and not its interior. The list of relationships shows ST_Touches and ST_Intersects true instead.
Using the ST_Contains Geometry Checker
- Paste the containing geometry, usually a polygon, into Geometry A, or select Load example.
- Paste the geometry that should be inside it into Geometry B.
- Select Check ST_Contains, or press Ctrl + Enter (Cmd + Enter on a Mac).
- Read the verdict and the explanation, then the matrix if you need the detail.
- Use Swap A and B to ask the reverse question, which is ST_Within.
When the output looks wrong
- ST_Contains is false for a point on the polygon's edge
- A polygon does not contain the points of its own boundary. The point touches the polygon instead, which the list of relationships below the verdict shows. If edge points should count, the PostGIS function is ST_Covers.
- The answer flips when I swap the geometries
- It should. ST_Contains(A, B) asks whether A holds B; the reverse is a different question, ST_Within. In a query, the containing geometry goes first: ST_Contains(region.geom, point.geom).
- Geometry B mixes points, lines and polygons that do not merge into one type
- A GeometryCollection holding different kinds of geometry has no single interior to compare, so it is refused rather than answered. Test the parts separately, or put only one kind of geometry in each input.
- A contains B but ST_Contains of the whole FeatureCollection is false
- A FeatureCollection is compared as one geometry: all of its features together must be inside A. If only some of them are, the answer is false. Test the features one at a time to find the ones outside.
Questions about the ST_Contains Geometry Checker
What does ST_Contains check?
That no point of B lies outside A and that at least one point of B's interior lies in A's interior. The DE-9IM pattern is T*****FF*. It is exactly ST_Within with the arguments swapped.
Why does a polygon not contain a point on its boundary?
Because the definition asks for B's interior to be inside A's interior, and a point on the edge is on A's boundary instead. This is the classic surprise with ST_Contains, and the reason ST_Covers exists.
Can a line be contained by a polygon if it runs along the edge?
Only if part of it runs through the inside. A line lying entirely along the boundary is not contained, because its interior never enters the polygon's interior. It touches the polygon.
Is the result the same as PostGIS?
For valid geometries, yes: the answer comes from the DE-9IM matrix computed by JSTS, a port of the same geometry library family PostGIS uses through GEOS. The matrix is shown so you can compare it with ST_Relate in your database.
Are my geometries sent anywhere?
No. Everything is computed in your browser, and nothing you paste leaves your device.