Learn

Within vs Contains vs Intersects

Learn how Within, Contains, and Intersects differ in GIS, why Within and Contains depend on direction, and why features on boundaries often behave differently from features in polygon interiors.

Geobble
introductoryexplainerSpatial Joins

Help readers choose the correct spatial predicate by explaining Within, Contains, and Intersects through direction, interior and boundary behaviour, and concrete spatial-join examples.

Within vs Contains vs Intersects

Within, Contains, and Intersects describe different topological relationships between geometries. Within asks whether geometry A lies inside geometry B. Contains asks the same relationship from the opposite direction: whether B lies inside A. Intersects is broader—it is true whenever the two geometries have at least one point in common.

For a point clearly inside a polygon, all three can appear to describe the same situation:

point WITHIN polygon
polygon CONTAINS point
point INTERSECTS polygon

The difference becomes important at boundaries, with overlapping geometries, and when choosing a predicate for a spatial join.

The three relationships at a glance

  • Situation: Point clearly inside polygon; Within: Point within polygon: true; Contains: Polygon contains point: true; Intersects: true

  • Situation: Point exactly on polygon boundary; Within: false; Contains: false; Intersects: true

  • Situation: Polygon completely inside another polygon; Within: Inner within outer: true; Contains: Outer contains inner: true; Intersects: true

  • Situation: Two polygons overlap partially; Within: false; Contains: false; Intersects: true

  • Situation: Two polygons only touch at their boundaries; Within: false; Contains: false; Intersects: true

  • Situation: Two separate geometries; Within: false; Contains: false; Intersects: false

This table captures the practical distinction, but the important idea is that these predicates describe geometry using concepts such as interior, boundary, and exterior rather than ordinary-language notions of “inside”.

What does Within mean?

Conceptually:

A WITHIN B

means that A is inside B.

The formal definition is slightly more precise. No point of A may lie outside B, and the interiors of A and B must have at least one point in common.

For the familiar point-in-polygon case:

School point WITHIN District polygon

returns true when the point lies in the polygon's interior.

That makes within a natural relationship for questions such as:

Which district is each school inside?

Which protected area contains each observation point?

Which census zone does each household location fall within?

The order matters:

school WITHIN district

makes sense.

district WITHIN school

normally does not.

The predicate is directional.

Contains is the inverse of Within

Contains expresses the corresponding relationship from the other geometry's point of view.

If:

A WITHIN B

is true, then:

B CONTAINS A

is also true.

PostGIS describes the two predicates explicitly as converses:

Contains(A, B) = Within(B, A)

So these are not two unrelated ideas.

Consider a school point and a district polygon:

school WITHIN district

and:

district CONTAINS school

describe the same geographic relationship from opposite directions.

This is particularly important when configuring a spatial join, because reversing the input layers without reconsidering the predicate can turn a sensible test into the wrong question.

Intersects is much broader

Intersects asks only whether two geometries share any point.

In mathematical terms:

A ∩ B ≠ ∅

That means all of these can intersect:

  • a point inside a polygon;

  • a point on a polygon boundary;

  • a road crossing a district;

  • two polygons that overlap;

  • two polygons that merely touch along an edge;

  • two lines crossing at one point.

Containment is therefore only one kind of intersection.

If:

A WITHIN B

then A necessarily intersects B.

If:

A CONTAINS B

then A necessarily intersects B.

But:

A INTERSECTS B

does not imply that either geometry is within the other.

Imagine two district polygons sharing a border:

District A | District B

They intersect along that boundary.

Neither contains the other.

Neither is within the other.

This is why intersects often produces more matches than readers expect.

The boundary case is the important one

Suppose a school lies exactly on a district boundary:

District A       District B
          |
          ● School
          |

It shares a point with both polygons.

So:

school INTERSECTS district_A

can be true.

And:

school INTERSECTS district_B

can also be true.

But the point is not in the interior of either polygon. Under the Simple Features definition used by systems such as PostGIS, a point lying entirely on a polygon boundary is therefore not within the polygon, and the polygon does not contain the point.

This gives:

school WITHIN district_A       false
district_A CONTAINS school     false
school INTERSECTS district_A   true

That behaviour often feels surprising because in ordinary language we might say the point is “part of” the district boundary.

Topological predicates use more precise definitions.

Why does this matter for spatial joins?

Suppose you have 5,000 facility points and administrative polygons.

You want to attach the district name to each facility.

Using:

facility WITHIN district

may work for almost every facility.

But a facility positioned exactly on a polygon boundary may receive no match.

Change the predicate to:

facility INTERSECTS district

and that facility may now match two districts.

Neither result is automatically wrong.

They answer different geometric questions.

The real decision is therefore:

What should a facility on the boundary mean in this dataset?

If administrative membership must resolve to one district, geometry alone may not contain enough information to make that decision. An authoritative district identifier may be preferable.

That is one reason an attribute join can sometimes be stronger than a spatial join.

Intersects is not a safer version of Within

A common troubleshooting habit is:

Within returned too few features, so use Intersects.

That can make a missing match appear, but it can also change the semantics of the analysis.

Suppose a road merely touches the corner of a protected-area polygon.

With intersects, that road is a match.

If the intended question was:

Which roads pass through protected areas?

a boundary touch may or may not represent what you actually mean by “pass through”.

Likewise, two polygons that share only an edge intersect even though they have no overlapping area.

So intersects should not be treated as:

Within, but more forgiving.

It represents a genuinely broader spatial relationship.

Partial overlap demonstrates the difference clearly

Consider two polygons:

   ┌──────────┐
   │    A     │
   │      ┌───┼─────┐
   └──────┼───┘  B  │
          └─────────┘

Part of A overlaps part of B.

Neither polygon lies completely inside the other.

Therefore:

A WITHIN B      false
A CONTAINS B    false
A INTERSECTS B  true

The same is true in the opposite direction for within and contains.

This is why polygon-to-polygon joins using intersects can produce many matches. A municipality might intersect several watersheds, flood zones, land-cover polygons, or service regions.

Those multiple records may describe legitimate geographic relationships rather than duplicates.

Equal geometries provide another subtle case

It is tempting to assume that contains means “strictly larger than”.

That is not how the standard relationship works.

In PostGIS, Within and Contains are reflexive: a valid geometry is within itself and contains itself.

So two topologically equal polygons can satisfy both relationships.

If you specifically need the idea:

A contains B and B must not be equal to A

then a stricter predicate such as ContainsProperly may be more appropriate in systems that provide it.

This illustrates why function names should not be interpreted purely through everyday English.

The underlying topological definition matters.

What about Covers?

Covers is another predicate worth knowing because it addresses precisely some of the boundary behaviour that makes contains surprising.

Conceptually, covers asks whether every point of B lies in A, without requiring their interiors to intersect in the same way that contains does.

That means a polygon can cover a point lying on its boundary even when it does not formally contain that point.

Similarly, CoveredBy provides the inverse relationship.

This can sometimes represent the real question more closely than contains or within.

But it should not be introduced merely to make inconvenient results disappear. The predicate still needs to match the intended geographic meaning.

A future Covers vs Contains article can treat that distinction in detail.

Invalid geometry can make predicate results unreliable

All of these relationships assume that the geometries themselves are meaningful.

A malformed polygon can have:

  • self-intersections;

  • incorrectly structured rings;

  • collapsed sections;

  • other topological defects.

PostGIS explicitly warns against using ST_Within and ST_Contains with invalid geometries because the results may be unexpected.

So if a predicate behaves inexplicably across many features, the problem may not be the predicate.

It may be the geometry.

This becomes especially important before large spatial joins, overlays, and other topology-dependent operations.

Which predicate should you use?

A practical starting point is:

Use Within when the question is:

Is A inside B?

Examples:

school WITHIN district
observation WITHIN protected_area
parcel WITHIN municipality

Use Contains when you are asking the inverse:

Does A contain B?

Examples:

district CONTAINS school
protected_area CONTAINS observation
municipality CONTAINS parcel

Use Intersects when any shared location should count

Examples:

road INTERSECTS flood_zone
municipality INTERSECTS watershed
pipeline INTERSECTS protected_area

But always ask whether boundary-only contact should count.

If it should not, intersects may be too broad.

The predicate is part of the question

Within, Contains, and Intersects are sometimes presented as technical switches in a GIS dialog.

They are more important than that.

Selecting a predicate defines what your analysis considers to be a relationship.

For a point clearly inside a polygon, the choice may seem irrelevant:

point WITHIN polygon
polygon CONTAINS point
point INTERSECTS polygon

all describe compatible facts.

At the boundary, that apparent equivalence disappears.

For overlapping polygons, it disappears again.

And in a spatial join involving thousands of features, those edge cases can determine whether records vanish, multiply, or attach to unexpected features.

The most useful rule is therefore not:

Use within for points and intersects for everything else.

It is:

Choose the predicate whose formal geographic relationship matches the question you are actually asking.


References

  1. PostGIS — ST_Within. Defines Within, including its interior requirement, relationship to geometry boundaries, and inverse relationship with Contains. PostGIS — ST_Within

  2. PostGIS — ST_Contains. Defines Contains, its relationship to Within, and the important boundary condition under which points or lines lying entirely on a geometry boundary are not considered contained. PostGIS — ST_Contains

  3. PostGIS — ST_Intersects. Defines Intersects as geometries having at least one point in common and provides its DE-9IM relationship patterns. PostGIS — ST_Intersects

  4. Open Geospatial Consortium — Simple Feature Access, Part 1: Common Architecture. Defines the Simple Features geometry model and topological relationships on which these predicates are based. OGC — Simple Feature Access, Part 1