Spatial Operations Explained

Learn buffer clip union intersection and difference operations with real GeoJSON examples you can paste into tools.

What Are Spatial Operations?

Spatial operations transform, combine, or analyze geometries based on their geographic relationships. Unlike attribute queries that filter by property values, spatial operations work directly with coordinate geometry — computing intersections, measuring distances, merging shapes, or deriving new geometries from existing ones. The six operations below cover the majority of real-world GeoJSON processing workflows.

Buffer

A buffer creates a polygon at a fixed distance around a geometry. Input any point, line, or polygon; specify a radius; receive a new polygon representing the area within that distance. Buffers are the foundation of proximity analysis.

Real Scenario: 1km Exclusion Zone Around a School

A city planning department needs to identify all liquor license applications within 1km of any school. The input is a Point feature at the school's location. The output is a circular Polygon with a radius of 1,000 meters. Any liquor license application whose point geometry falls inside that polygon is flagged for review.

json// Input: School location (Point)
{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [-73.9857, 40.7484]
  },
  "properties": {
    "name": "PS 116 Mary Lindley Murray",
    "type": "elementary_school"
  }
}

// Output: 1km buffer (Polygon, ~64 vertices by default)
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-73.9857, 40.7574],
      [-73.9731, 40.7561],
      [-73.9622, 40.7525],
      "... 60 more coordinate pairs ...",
      [-73.9857, 40.7574]
    ]]
  },
  "properties": {
    "source_feature": "PS 116 Mary Lindley Murray",
    "buffer_radius_m": 1000
  }
}

Buffer radius units depend on the CRS. For WGS84 GeoJSON, most tools accept a radius in kilometers or meters and handle the unit conversion internally. Turf.js's turf.buffer(feature, 1, {units: 'kilometers'}) produces the correct result without manual degree conversion. Use the GeoJSON buffer tool to generate buffers with a configurable radius and vertex count.

Buffer a line to model noise corridors along highways or flight paths. Buffer a polygon to model setback requirements around protected wetlands. The operation generalizes across all geometry types.

Clip

A clip (also called a cookie-cutter or mask operation) trims a set of input features to the boundary of a clipping polygon. Features entirely inside the boundary pass through unchanged. Features entirely outside are removed. Features that cross the boundary are split, retaining only the portion inside.

Real Scenario: Extract Features Within a City Boundary

A transit agency wants to extract all bike lanes from a regional dataset to produce a city-specific layer. The input is a FeatureCollection of LineString geometries covering a three-county area, plus a Polygon representing the city boundary. The output is a FeatureCollection of LineStrings with edges trimmed exactly to the city boundary.

json// Input 1: Bike lane crossing the city boundary
{
  "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [-122.4900, 37.8199],
      [-122.4783, 37.8199],
      [-122.4650, 37.8199]
    ]
  },
  "properties": { "name": "Coastal Trail Connector", "surface": "asphalt" }
}

// Input 2: City boundary (clipping polygon)
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-122.4850, 37.8100],
      [-122.4700, 37.8100],
      [-122.4700, 37.8280],
      [-122.4850, 37.8280],
      [-122.4850, 37.8100]
    ]]
  },
  "properties": { "name": "City Boundary" }
}

// Output: Trimmed line (only the segment inside the boundary)
{
  "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [-122.4850, 37.8199],
      [-122.4783, 37.8199],
      [-122.4700, 37.8199]
    ]
  },
  "properties": { "name": "Coastal Trail Connector", "surface": "asphalt" }
}

The clip preserves original properties on the output features. Line geometries longer than the clipping polygon may be split into multiple segments — one per separate entry into the boundary. Use the GeoJSON clip tool to clip a FeatureCollection to any polygon boundary.

Union

Union merges two or more overlapping or adjacent polygons into a single polygon covering the combined area. Boundaries between the input polygons are dissolved where they touch or overlap, and the outer perimeter of the combined shape becomes the output geometry.

Real Scenario: Merge Overlapping Land Parcels

A property developer has acquired two adjacent parcels that partially overlap due to a surveying discrepancy. To calculate the total buildable area and generate a single parcel boundary for permit applications, they union the two polygon geometries. The output is a single polygon with one continuous boundary and properties that can be set to reflect the merged parcel.

json// Input: Two overlapping parcels
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [[
          [-73.9870, 40.7480],
          [-73.9850, 40.7480],
          [-73.9850, 40.7495],
          [-73.9870, 40.7495],
          [-73.9870, 40.7480]
        ]]
      },
      "properties": { "parcel_id": "A-1042", "area_sqm": 1680 }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [[
          [-73.9855, 40.7488],
          [-73.9835, 40.7488],
          [-73.9835, 40.7503],
          [-73.9855, 40.7503],
          [-73.9855, 40.7488]
        ]]
      },
      "properties": { "parcel_id": "A-1043", "area_sqm": 1540 }
    }
  ]
}

// Output: Single merged polygon (overlap resolved, combined perimeter)
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-73.9870, 40.7480],
      [-73.9850, 40.7480],
      [-73.9850, 40.7488],
      [-73.9835, 40.7488],
      [-73.9835, 40.7503],
      [-73.9855, 40.7503],
      [-73.9855, 40.7495],
      [-73.9870, 40.7495],
      [-73.9870, 40.7480]
    ]]
  },
  "properties": { "parcel_ids": "A-1042,A-1043", "area_sqm": 2890 }
}

The merged area (2,890 sqm) is less than the sum of both parcels (3,220 sqm) because the overlapping region is counted once. Use the GeoJSON union tool to merge any number of polygon features.

Intersection

Intersection returns the geometry that is common to both input polygons — the area where they overlap. If the inputs do not overlap, the result is an empty geometry. Intersection is used to quantify how much of one area falls within another.

Real Scenario: Overlap Between Flood Zone and Residential Area

An emergency management agency needs to identify residential parcels at risk by finding the exact overlap between the FEMA 100-year flood zone and a residential zoning district. The intersection polygon represents the area that is simultaneously in the flood zone and zoned residential — the highest-priority area for flood insurance outreach.

json// Input 1: FEMA 100-year flood zone (partial)
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-122.4820, 37.8180],
      [-122.4750, 37.8180],
      [-122.4750, 37.8220],
      [-122.4820, 37.8220],
      [-122.4820, 37.8180]
    ]]
  },
  "properties": { "zone": "AE", "bfe_ft": 14 }
}

// Input 2: Residential zoning district
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-122.4800, 37.8170],
      [-122.4730, 37.8170],
      [-122.4730, 37.8210],
      [-122.4800, 37.8210],
      [-122.4800, 37.8170]
    ]]
  },
  "properties": { "zone_code": "R-2", "units_per_acre": 8 }
}

// Output: Overlapping area only
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-122.4800, 37.8180],
      [-122.4750, 37.8180],
      [-122.4750, 37.8210],
      [-122.4800, 37.8210],
      [-122.4800, 37.8180]
    ]]
  },
  "properties": {}
}

After computing the intersection, calculate the area using Turf.js turf.area(intersection) to get the at-risk area in square meters. The result drives reporting: "X,XXX residential properties covering Y hectares fall within the AE flood zone." Use the GeoJSON intersection tool to compute overlaps interactively.

Difference

Difference subtracts one polygon from another, returning the area of the first polygon that does not overlap the second. The operation is directional: A minus B is not the same as B minus A. If the second polygon is entirely outside the first, the output equals the first polygon unchanged.

Real Scenario: Subtract a Park From a City District

A city zoning analyst needs to calculate the net developable area in a district by subtracting all protected parkland. The input is the district boundary polygon (A) and a park polygon (B). The output is the district boundary with the park area removed — a polygon with a hole, or a multi-polygon if the park splits the district.

json// Input A: City district polygon
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-73.9880, 40.7470],
      [-73.9820, 40.7470],
      [-73.9820, 40.7510],
      [-73.9880, 40.7510],
      [-73.9880, 40.7470]
    ]]
  },
  "properties": { "district": "Midtown South", "area_ha": 48.6 }
}

// Input B: Central park polygon (to subtract)
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [[
      [-73.9865, 40.7482],
      [-73.9845, 40.7482],
      [-73.9845, 40.7498],
      [-73.9865, 40.7498],
      [-73.9865, 40.7482]
    ]]
  },
  "properties": { "name": "Bryant Park Annex", "protected": true }
}

// Output: District polygon with park area removed (polygon with hole)
{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [-73.9880, 40.7470],
        [-73.9820, 40.7470],
        [-73.9820, 40.7510],
        [-73.9880, 40.7510],
        [-73.9880, 40.7470]
      ],
      [
        [-73.9865, 40.7482],
        [-73.9865, 40.7498],
        [-73.9845, 40.7498],
        [-73.9845, 40.7482],
        [-73.9865, 40.7482]
      ]
    ]
  },
  "properties": { "district": "Midtown South", "net_developable_ha": 44.1 }
}

The second ring in the output coordinates array represents the hole — the GeoJSON polygon ring winding convention requires exterior rings to be counterclockwise and holes to be clockwise. Use the GeoJSON difference tool to subtract any polygon from another and inspect the resulting geometry.

Dissolve

Dissolve merges a collection of polygons that share a common attribute value, combining all features with the same property into a single (possibly multi-part) geometry. Unlike union which merges all features regardless of attributes, dissolve groups by a field first, producing one output feature per unique attribute value.

Real Scenario: Combine US States Into Census Regions

The US Census Bureau divides the 50 states into 4 regions (Northeast, Midwest, South, West). To visualize regional data, you need to dissolve state polygons grouped by their region property. The output is a FeatureCollection with 4 features — one polygon per region, each representing the combined shape of all states in that region.

json// Input: Individual state features with region property (excerpt)
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": { "type": "Polygon", "coordinates": [[...]] },
      "properties": { "name": "California", "region": "West", "pop": 39538223 }
    },
    {
      "type": "Feature",
      "geometry": { "type": "Polygon", "coordinates": [[...]] },
      "properties": { "name": "Oregon", "region": "West", "pop": 4237256 }
    },
    {
      "type": "Feature",
      "geometry": { "type": "Polygon", "coordinates": [[...]] },
      "properties": { "name": "New York", "region": "Northeast", "pop": 20201249 }
    }
  ]
}

// Output: Dissolved by "region" property (4 features total)
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [[[[...California coords...]]], [[[...Oregon coords...]]], "..."]
      },
      "properties": { "region": "West", "feature_count": 13 }
    },
    {
      "type": "Feature",
      "geometry": { "type": "MultiPolygon", "coordinates": [[[[...]]]] },
      "properties": { "region": "Northeast", "feature_count": 9 }
    }
  ]
}

Non-contiguous states in the same region (Hawaii and the contiguous West Coast states, for example) produce a MultiPolygon output rather than a single Polygon. The dissolve operation preserves the dissolved field as a property on each output feature and optionally aggregates numeric fields (sum, mean, count). Use the GeoJSON dissolve tool to dissolve by any string property.

Combining Operations: A Real Workflow

Individual spatial operations become powerful when chained. A common workflow in urban planning, environmental analysis, and logistics combines three or more operations to derive a result that no single operation could produce.

Workflow: Find Residential Area Within Walking Distance of a Transit Stop, Clipped to a District

Goal: determine how much residential-zoned land in the Mission District of San Francisco falls within 800m (a 10-minute walk) of a BART station entrance.

Step 1 — Buffer: Apply an 800m buffer to the BART station Point feature using the buffer tool. Output: a circular Polygon with an 800m radius centered on the station at [-122.4183, 37.7624].

json// Step 1 output: 800m buffer around 24th St Mission BART
{
  "type": "Feature",
  "geometry": { "type": "Polygon", "coordinates": [[...64-vertex circle...]] },
  "properties": { "radius_m": 800, "source": "24th St Mission BART" }
}

Step 2 — Intersection: Intersect the buffer polygon with the Mission District boundary using the intersection tool. This trims the walking-distance circle to only the portion within the district, excluding areas in adjacent neighborhoods. Output: an irregular polygon representing the district area within walking distance.

json// Step 2 output: Buffer intersected with Mission District boundary
{
  "type": "Feature",
  "geometry": { "type": "Polygon", "coordinates": [[...irregular boundary...]] },
  "properties": {}
}

Step 3 — Clip: Clip the residential zoning parcels FeatureCollection to the Step 2 intersection polygon using the clip tool. This retains only the residential parcels that fall within both the walking-distance zone and the district boundary.

Step 4 — Area calculation: Sum the area of all clipped residential parcels using turf.area(). The result — for example, 142 hectares — is the answer: 142ha of residential land in the Mission District is within a 10-minute walk of 24th St Mission BART.

This workflow, combining buffer + intersection + clip + area aggregation, is a pattern that recurs across transit planning, retail site selection, emergency response planning, and environmental impact assessment. Mastering the six operations above and understanding how to sequence them covers the vast majority of real-world spatial analysis tasks.