# Earthwork Calculator: Cut & Fill, Mass Diagram, Volumes (`jumblemog/earthwork-calculator`) Actor

Earthwork volumes from plain text: cut and fill from cross-sections with the mass diagram and shrinkage, grid (borrow-pit) volumes and the balanced grade, and pits, trenches and stockpiles, with truck loads and a chart.

- **URL**: https://apify.com/jumblemog/earthwork-calculator.md
- **Developed by:** [Jumble Mog](https://apify.com/jumblemog) (community)
- **Categories:** AI, Automation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Earthwork Calculator: Cut & Fill, Mass Diagram, Volumes

**Earthwork quantities from one line of text.** Paste your cross-section end areas (`0+00 cut 0 fill 0; 1+00 cut 120 fill 0; ...; shrinkage 10%`), a grid of cut and fill depths or existing elevations (`borrow pit grid 20 ft squares, cut depths: 2.1 1.8 1.5; 1.9 1.4 1.0; ...`), or describe a pit, trench or stockpile (`pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1`). You get back:

- **Cut and fill between cross-sections**: volumes by average end areas (with the pyramid rule where cut or fill runs out to zero), shrinkage applied to the cut, the mass diagram ordinates, its highest and lowest points, the balance points (where cut and fill even out) and whether the job ends in waste or borrow.
- **Grid (borrow-pit) volumes**: cut and fill from corner depths, or from existing elevations and a proposed grade; with no proposed grade, the level grade that balances cut and fill.
- **Pits, trenches and stockpiles**: excavation volumes with side slopes (prismoidal formula), trench volumes, and conical or ridged stockpiles from their size or angle of repose.
- **Hauling**: loose volume after swell and the number of truck loads.
- **A chart**: end areas with the mass diagram, the grid colored by cut and fill depth, or the shape's section drawn to scale.

US units (feet, cubic yards) or metric (metres, cubic metres); results come back in the units you wrote.

It's made for:

- Civil engineers and estimators doing cut and fill take-offs for roads, pads and site grading.
- Contractors pricing excavation, hauling and trucks.
- Civil engineering and surveying students working earthwork and mass-haul problems.
- AI agents that need correct earthwork quantities instead of a guess.

![Earthwork from cross-sections drawn by this Actor: end areas from 0+00 to 7+00 with cut bars in orange above the line and fill bars in blue below, and the mass diagram rising to about 1,090 yd³ at 4+00 and falling to 30.9 yd³ of excess cut at 7+00](https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/earthwork-calculator-example.png?signature=1scU60kVm1zkPKVF5cQsp)

### How to use it

1. Write **Cross-sections, grids and shapes**, one per entry. The form has examples.
2. Optionally set the **Units** for requests written without one.
3. Click **Start**. Each request is a row in the results, with its summary, chart and report.

#### What you can write

| You write | It means |
|---|---|
| `0+00 cut 0 fill 0; 1+00 cut 120 fill 0; ... sq ft` | Cross-sections: station, cut end area, fill end area |
| `shrinkage 10%` | Cut shrinks by 10% when placed as fill (a negative value is swell) |
| `grid 20 ft squares, cut depths: 2.1 1.8 1.5; 1.9 1.4 1.0` | Corner depths row by row (positive cut, negative fill) |
| `grid 10 m squares, existing elevations: ...; proposed grade 100.5` | Elevations and a level grade (without one you get the balanced grade) |
| `pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1` | An excavation with sloped sides (`vertical sides` for none) |
| `trench 100 ft long, 3 ft wide, 6 ft deep, side slopes 1:1` | A trench with vertical ends |
| `conical stockpile 40 ft diameter, 12 ft high` | A cone (any two of diameter, height, angle of repose) |
| `stockpile 60 x 20 m base, angle of repose 35` | A ridged pile (add a height for a flat top) |
| `swell 25%, trucks of 10 m3` | Loose volume and truck loads |

The same as objects: `{"type": "sections", "sections": [{"station": "0+000", "cut": 45, "fill": 0}, {"station": "0+020", "cut": 30, "fill": 5}], "shrinkage": "15%", "units": "m"}` or `{"type": "grid", "existing": [[10, 10.4], [9.8, 10.1]], "proposed": 9.5, "spacing": 5, "units": "m"}`.

### Examples

- The cross-sections above → cut 1,450.6 yd³, fill 1,274.7 yd³; cut after 10% shrinkage 1,305.6 yd³; 30.9 yd³ of excess cut to waste.
- `borrow pit grid 20 ft squares, cut depths: 2.1 1.8 1.5 1.2; 1.9 1.4 1.0 0.6; 1.2 0.8 0.5 -0.3 ft` → cut 103.8 yd³, fill 0.1 yd³.
- `grid 10 m squares, existing elevations: 102.4 101.9 101.2; 101.8 101.0 100.6; 101.1 100.4 99.8` → balanced grade 101.119 m, 85.7 m³ of cut and of fill.
- `pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3` → 2,556.0 m³ bank, 3,195.0 m³ loose, 320 truck loads.
- `conical stockpile 40 ft diameter, 12 ft high` → 186.2 yd³, faces at 31.0°.

### How-to examples

Each example is a complete input; the results are from runs of the Actor (also listed under **Examples**).

#### How to calculate cut and fill from cross-section end areas

```json
{"requests": ["0+00 cut 0 fill 0; 1+00 cut 120 fill 0; 2+00 cut 185 fill 0; 3+00 cut 90 fill 15; 4+00 cut 20 fill 80; 5+00 cut 0 fill 160; 6+00 cut 0 fill 110; 7+00 cut 0 fill 0 sq ft; shrinkage 10%"]}
```

Result: cut 1,450.6 yd³ and fill 1,274.7 yd³; cut after 10% shrinkage is 1,305.6 yd³, leaving 30.9 yd³ of excess cut to waste. The chart has the mass diagram.

#### How to find the balanced grade of a site from a grid of elevations

```json
{"requests": ["grid 10 m squares, existing elevations: 102.4 101.9 101.2; 101.8 101.0 100.6; 101.1 100.4 99.8"]}
```

Result: balanced grade 101.119 m, with 85.7 m³ of cut and of fill. With cut depths instead, `borrow pit grid 20 ft squares, cut depths: ...` gives the borrow volume.

#### How to calculate the volume of a pit and the truck loads

```json
{"requests": ["pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3"]}
```

Result: 2,556.0 m³ bank, 3,195.0 m³ loose and 320 truck loads. `conical stockpile 40 ft diameter, 12 ft high` gives 186.2 yd³ with faces at 31.0°.

#### How to let an AI agent do earthwork take-offs

Add this Actor to the [Apify MCP server](https://mcp.apify.com) with `https://mcp.apify.com/?tools=jumblemog/earthwork-calculator`. The agent pastes the stations, grid or shape as one line and answers with the cut, fill, waste and truck loads.

### FAQ

**Which method does it use for cross-sections?** Average end areas between stations, and the pyramid rule where one end area is zero; the prismoidal correction isn't applied.

**Does it compute end areas from ground points?** No. It works from the cut and fill area at each station.

**Can a grid have missing points?** Yes. Mark blanks with `-` or `x`; squares missing a corner are left out, so irregular sites work.

**Which shapes can it measure?** Pits, trenches and stockpiles with side slopes, by the prismoidal formula, which is exact for plane slopes, and cones.

### Input

| Field | What it is |
|---|---|
| `requests` | The cross-sections, grids and shapes, as lines of text or objects (up to 200 per run) |
| `units` | For requests without a unit: `m` (metres) or `ft` (feet) |
| `charts` | Draw a chart for each request (default on) |

### Output

One dataset item per request, also saved together in the run's `OUTPUT` record:

```json
{
  "request": 1, "status": "ok", "type": "sections", "title": "Earthwork, 0+00.00 to 7+00.00",
  "summary": "Cut 1,450.6 yd³, fill 1,274.7 yd³ (cut after 10% shrinkage 1,305.6); excess 30.9 yd³.",
  "totals": {"cut": 1450.62, "fill": 1274.69, "shrinkage": 10, "cutAfterShrinkage": 1305.56, "net": 30.8642,
             "result": "waste (excess cut)", "maxMassOrdinate": 1088.89, "minMassOrdinate": 0,
             "balancePoints": [], "length": 700},
  "sections": [{"station": "1+00.00", "cutArea": 120, "fillArea": 0, "length": 100, "cutVolume": 148.148,
                "fillVolume": 0, "adjustedCut": 133.333, "massOrdinate": 133.333}, "..."],
  "units": {"length": "ft", "area": "sq ft", "volume": "yd³", "depth": "ft", "angle": "°"},
  "imageUrl": "https://api.apify.com/v2/key-value-stores/.../records/001-Earthwork-0-00-00-to-7-00-00.png"
}
```

Grids add `grid` (squares, area, balanced grade) and `depths`; shapes add `shape` (dimensions, top size, volume); `haul` appears when you give a swell or truck size. Every item has `units`, `summary`, `warnings`, `notes` (the method and assumptions), a Markdown `report` and links to the chart and report. A request that can't be computed has `"status": "failed"` and the reason in `error`, and isn't billed.

### How it works

1. **Cross-sections**: V = L·(A1 + A2)/2 between stations; where one end area is zero the material tapers out, so V = L·A/3 (the pyramid rule). Volumes in cubic yards (27 cu ft) for feet.
2. **Mass diagram**: running total of cut after shrinkage minus fill; balance points where it crosses zero, linear between sections.
3. **Grid**: each square is A·(sum of its four corner depths)/4; a square with both cut and fill splits as A·(Σcut)²/(4·Σ|h|) and A·(Σfill)²/(4·Σ|h|).
4. **Balanced grade**: corner elevations weighted by how many squares share them (1, 2, 3 or 4).
5. **Shapes**: the prismoidal formula h/6·(A_bottom + 4·A_mid + A_top), exact for plane side slopes; cones πr²h/3.
6. **Hauling**: loose volume = bank volume × (1 + swell); truck loads rounded up.

### Pricing

You pay one low price per request, at the prices shown on this page; pits, trenches and stockpiles cost less than cross-sections and grids. The chart and report are included. Requests that can't be computed are never charged. If you set a maximum cost per run, the Actor stops before a request that wouldn't fit.

### Speed

Each request takes a few milliseconds. A run through the API answers in about 10 seconds, including the cloud container starting.

### Tips and limits

- **End areas**: this Actor works from the cut and fill area at each station; it doesn't compute areas from ground and template cross-section points.
- **Average end areas** overstate a little where sections change shape fast; the prismoidal correction isn't applied.
- **Grids**: depths are existing minus proposed (positive cut). Squares missing a corner are left out, so irregular sites work with blanks (`-` or `x`).
- **Shrinkage and swell** vary by soil; the defaults are none for shrinkage and 25% for swell when you ask for truck loads.
- **Limits**: 200 requests per run.

### For AI agents and developers

This Actor works with the [Apify MCP server](https://mcp.apify.com), so AI agents can call it as a tool. Pass `requests` as plain text and read `summary`, `totals`, `sections`, `grid`, `shape`, `haul` and `warnings`. A direct API call that waits for the answer:

```bash
curl -X POST "https://api.apify.com/v2/acts/jumblemog~earthwork-calculator/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests": ["pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3"]}'
```

`run-sync` instead returns the run's `OUTPUT`: the status, the counts and every result as JSON.

In Python, with the `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("jumblemog/earthwork-calculator").call(run_input={
    "requests": [{"type": "sections", "units": "ft", "shrinkage": "10%",
                  "sections": [{"station": "0+00", "cut": 0, "fill": 0},
                               {"station": "1+00", "cut": 120, "fill": 0},
                               {"station": "2+00", "cut": 185, "fill": 0},
                               {"station": "3+00", "cut": 90, "fill": 15}]}],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["summary"])
```

### Credits

- Charts: [Vega-Lite](https://vega.github.io/vega-lite/) and [vl-convert](https://github.com/vega/vl-convert) (BSD-3-Clause), with the [Inter](https://rsms.me/inter/) font (SIL Open Font License).
- Methods: Wright and Dixon, *Highway Engineering*; Ghilani and Wolf, *Elementary Surveying* (earthwork chapter).

# Actor input Schema

## `requests` (type: `array`):

One request per entry, as a line of text or an object. Cross-sections: stations with their cut and fill end areas ('0+00 cut 0 fill 0; 1+00 cut 120 fill 10; ...' in sq ft, or '0+000 ...' in m²), optional shrinkage ('shrinkage 10%'), swell and truck size ('swell 25%, trucks of 12 cy'): cut and fill volumes, the mass diagram, balance points and the waste or borrow. Grid (borrow pit): the square size ('20 ft squares', '10 x 20 m cells') and corner cut depths row by row, fill negative ('cut depths: 2.1 1.8 1.5; 1.9 1.4 1.0'), or 'existing elevations: ...' with 'proposed 100.0' (a level), a proposed grid, or nothing for the balanced grade; 'x' marks a point outside the area. Shapes: pits with sloped sides ('pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1'), trenches ('trench 100 ft long, 3 ft wide, 6 ft deep, 1:1'), conical piles ('40 ft diameter, 12 ft high', or with the angle of repose) and long piles ('stockpile 30 x 10 m base, angle of repose 35°'). Object fields: type (sections, grid or shape), sections \[{station, cut, fill}] or stations, cut, fill; pyramid; depths, existing, proposed, spacing, dx, dy; shape (pit, trench, cone, pile), length, width, depth, height, diameter, slope, repose; shrinkage, swell, truck; units, title, text.

## `units` (type: `string`):

For requests without a unit. ft, sq ft, cy or 1+00 stations switch a request to feet; m, m², m³ or 0+000 stations to metres.

## `charts` (type: `boolean`):

End areas with the mass diagram, the grid coloured by depth, or the shape's cross-section to scale.

## Actor input object example

```json
{
  "requests": [
    "0+00 cut 0 fill 0; 1+00 cut 120 fill 0; 2+00 cut 185 fill 0; 3+00 cut 90 fill 15; 4+00 cut 20 fill 80; 5+00 cut 0 fill 160; 6+00 cut 0 fill 110; 7+00 cut 0 fill 0 sq ft; shrinkage 10%",
    "borrow pit grid 20 ft squares, cut depths: 2.1 1.8 1.5 1.2; 1.9 1.4 1.0 0.6; 1.2 0.8 0.5 -0.3 ft",
    "grid 10 m squares, existing elevations: 102.4 101.9 101.2; 101.8 101.0 100.6; 101.1 100.4 99.8",
    "pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3",
    "trench 100 ft long, 3 ft wide, 6 ft deep, side slopes 1:1",
    "conical stockpile 40 ft diameter, 12 ft high",
    {
      "type": "sections",
      "sections": [
        {
          "station": "0+000",
          "cut": 45,
          "fill": 0
        },
        {
          "station": "0+020",
          "cut": 30,
          "fill": 5
        },
        {
          "station": "0+040",
          "cut": 0,
          "fill": 38
        },
        {
          "station": "0+060",
          "cut": 0,
          "fill": 20
        }
      ],
      "shrinkage": "15%",
      "units": "m"
    }
  ],
  "units": "m",
  "charts": true
}
```

# Actor output Schema

## `results` (type: `string`):

One row per request: the summary and chart.

## `output` (type: `string`):

The OUTPUT record: every result in one JSON object.

## `files` (type: `string`):

Charts (PNG and SVG) and Markdown reports in the run's key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "requests": [
        "0+00 cut 0 fill 0; 1+00 cut 120 fill 0; 2+00 cut 185 fill 0; 3+00 cut 90 fill 15; 4+00 cut 20 fill 80; 5+00 cut 0 fill 160; 6+00 cut 0 fill 110; 7+00 cut 0 fill 0 sq ft; shrinkage 10%",
        "borrow pit grid 20 ft squares, cut depths: 2.1 1.8 1.5 1.2; 1.9 1.4 1.0 0.6; 1.2 0.8 0.5 -0.3 ft",
        "grid 10 m squares, existing elevations: 102.4 101.9 101.2; 101.8 101.0 100.6; 101.1 100.4 99.8",
        "pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3",
        "trench 100 ft long, 3 ft wide, 6 ft deep, side slopes 1:1",
        "conical stockpile 40 ft diameter, 12 ft high",
        {
            "type": "sections",
            "sections": [
                {
                    "station": "0+000",
                    "cut": 45,
                    "fill": 0
                },
                {
                    "station": "0+020",
                    "cut": 30,
                    "fill": 5
                },
                {
                    "station": "0+040",
                    "cut": 0,
                    "fill": 38
                },
                {
                    "station": "0+060",
                    "cut": 0,
                    "fill": 20
                }
            ],
            "shrinkage": "15%",
            "units": "m"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jumblemog/earthwork-calculator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "requests": [
        "0+00 cut 0 fill 0; 1+00 cut 120 fill 0; 2+00 cut 185 fill 0; 3+00 cut 90 fill 15; 4+00 cut 20 fill 80; 5+00 cut 0 fill 160; 6+00 cut 0 fill 110; 7+00 cut 0 fill 0 sq ft; shrinkage 10%",
        "borrow pit grid 20 ft squares, cut depths: 2.1 1.8 1.5 1.2; 1.9 1.4 1.0 0.6; 1.2 0.8 0.5 -0.3 ft",
        "grid 10 m squares, existing elevations: 102.4 101.9 101.2; 101.8 101.0 100.6; 101.1 100.4 99.8",
        "pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3",
        "trench 100 ft long, 3 ft wide, 6 ft deep, side slopes 1:1",
        "conical stockpile 40 ft diameter, 12 ft high",
        {
            "type": "sections",
            "sections": [
                {
                    "station": "0+000",
                    "cut": 45,
                    "fill": 0,
                },
                {
                    "station": "0+020",
                    "cut": 30,
                    "fill": 5,
                },
                {
                    "station": "0+040",
                    "cut": 0,
                    "fill": 38,
                },
                {
                    "station": "0+060",
                    "cut": 0,
                    "fill": 20,
                },
            ],
            "shrinkage": "15%",
            "units": "m",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jumblemog/earthwork-calculator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "requests": [
    "0+00 cut 0 fill 0; 1+00 cut 120 fill 0; 2+00 cut 185 fill 0; 3+00 cut 90 fill 15; 4+00 cut 20 fill 80; 5+00 cut 0 fill 160; 6+00 cut 0 fill 110; 7+00 cut 0 fill 0 sq ft; shrinkage 10%",
    "borrow pit grid 20 ft squares, cut depths: 2.1 1.8 1.5 1.2; 1.9 1.4 1.0 0.6; 1.2 0.8 0.5 -0.3 ft",
    "grid 10 m squares, existing elevations: 102.4 101.9 101.2; 101.8 101.0 100.6; 101.1 100.4 99.8",
    "pit 20 x 30 m bottom, 3 m deep, side slopes 1.5:1, swell 25%, trucks of 10 m3",
    "trench 100 ft long, 3 ft wide, 6 ft deep, side slopes 1:1",
    "conical stockpile 40 ft diameter, 12 ft high",
    {
      "type": "sections",
      "sections": [
        {
          "station": "0+000",
          "cut": 45,
          "fill": 0
        },
        {
          "station": "0+020",
          "cut": 30,
          "fill": 5
        },
        {
          "station": "0+040",
          "cut": 0,
          "fill": 38
        },
        {
          "station": "0+060",
          "cut": 0,
          "fill": 20
        }
      ],
      "shrinkage": "15%",
      "units": "m"
    }
  ]
}' |
apify call jumblemog/earthwork-calculator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jumblemog/earthwork-calculator"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/86gEkEWpN4Us6i2pb/builds/mYtqdM3FghbElMrEU/openapi.json
