Choosing a Base Surface for Stockpile Volumes

Two competent people process the same flight over the same stockpile and return volumes that differ by six percent. Neither made a mistake. One fitted a plane through the toe of the pile; the other used the terrain model from a survey flown before the material arrived. On a pile sitting in a shallow depression those two surfaces differ by thirty centimetres under the middle, and thirty centimetres over two thousand square metres is six hundred cubic metres.

The base surface is the largest discretionary choice in a volume computation, and it is usually made implicitly by whichever tool is in front of the operator. This page makes it explicit: what each candidate assumes, when each is right, and how to stop the chosen one drifting between surveys.

Why the base is a modelling assumption, not a measurement

The upper surface is measured: the drone saw the top of the pile and the reconstruction recorded it. The base is, by definition, the surface under the material — which the drone never saw. Every base is therefore a statement about what would be there if the pile were removed, and the four common candidates encode four different statements.

A fitted plane says the ground beneath is flat and continues the slope of the surrounding hardstanding. On a yard that has been graded, this is close to true. On natural ground with a hollow, it is not.

A prior terrain model says the ground beneath is what was measured before the material arrived. This is the only candidate grounded in observation, and it is right whenever it exists and whenever the ground has not been disturbed since — which on an active site is a real qualification, because loaders scrape the base as they work.

A fixed level says the ground is a constant elevation the client has specified, usually a design formation level. This is not an estimate of reality at all; it is a contractual reference, and a volume against it answers “how much material is above the design level”, which is often exactly the question.

A picked toe triangulation says the ground follows a surface interpolated through points a person selected around the base of the pile. It is the most flexible and the least reproducible: two operators pick different points, and the result depends on the pick.

What each base surface assumes about the ground beneath the pile Four panels, each showing the same stockpile cross-section over a different assumed base. The fitted plane runs straight through the toe and sits above a real hollow in the ground. The prior terrain model follows the hollow exactly, giving the largest volume. The fixed design level runs horizontally below both, answering a contractual question rather than a physical one. The picked toe triangulation follows an irregular path through selected points and lands between the others. Volume figures under each panel read eleven thousand nine hundred, twelve thousand five hundred, thirteen thousand eight hundred and twelve thousand one hundred cubic metres respectively. fitted plane assumes flat ground 11 900 m³ prior terrain the only measured base 12 500 m³ fixed level a contractual datum 13 800 m³ picked toe depends on the operator 12 100 m³ Same pile, same flight, same software: a sixteen percent spread. None of these is a processing error. They answer four different questions. The deliverable must say which question was answered.

Figure 1 — Four bases, four volumes, one pile. The spread is larger than any tolerance a client would accept, and it is invisible in the output file.

Minimal reproducible solution

Make the base an explicit, named, stored decision. The function below produces any of the four from a single declaration, and — critically — it persists the chosen base so that the next survey uses the same one.

import json
from pathlib import Path

import numpy as np
import rasterio


def resolve_base(mode: str, *, site_config: str, transform, shape_hw,
                 toe_xyz=None, prior_path=None) -> tuple[np.ndarray, dict]:
    """Produce the base surface for a site, reusing a stored one where it exists.

    The site config is the contract: once a base has been fixed for a site,
    later surveys read it back rather than re-deriving it, which is what stops
    a pile's volume moving when nothing has been delivered or removed.
    """
    cfg_path = Path(site_config)
    cfg = json.loads(cfg_path.read_text()) if cfg_path.exists() else {}

    if mode == "plane":
        if "plane" in cfg:
            a, b, c = cfg["plane"]                    # reuse the frozen fit
        else:
            if toe_xyz is None:
                raise ValueError("no stored plane and no toe points supplied")
            a, b, c = fit_toe_plane(*toe_xyz)
            cfg["plane"] = [a, b, c]
            cfg_path.write_text(json.dumps(cfg, indent=2))
        surface = plane_surface(a, b, c, transform, shape_hw)
        params = {"plane": [a, b, c], "frozen": "plane" in cfg}

    elif mode == "prior":
        if prior_path is None:
            raise ValueError("prior mode needs a pre-existing terrain raster")
        surface, _ = align_to_grid(prior_path, transform, shape_hw)
        params = {"prior": prior_path}

    elif mode == "fixed":
        level = cfg["fixed_level_m"]                  # must be in the config
        surface = np.full(shape_hw, level, dtype="float32")
        params = {"fixed_level_m": level}

    else:
        raise ValueError(f"unknown base mode {mode!r}")

    return surface, {"base_mode": mode, **params}

The frozen flag in the returned parameters is small and load-bearing. A volume computed against a freshly fitted plane and one computed against a frozen plane are not comparable, and a monitoring series that silently mixes them will show steps that look like material movement.

Note that picked-toe mode is deliberately absent. It can be supported — as a stored polygon of picked points, treated exactly like the frozen plane — but it should never be re-picked per survey, and making it awkward to do so is a feature.

Edge-case matrix

Situation Best base Why
Graded yard, no prior survey Fitted plane, frozen Ground genuinely is near-planar
Pre-clearance survey exists Prior terrain The only measured option
Contract references a formation level Fixed level Answers the question actually asked
Pile on natural undulating ground Prior terrain, else picked toe A plane misses the hollow
Pile against a retaining wall Prior terrain or fixed A plane fit is unconstrained on one side
Pile growing outward each month Frozen plane or prior A re-fitted plane tilts as the toe moves
Base scraped by loaders since the prior survey Fitted plane The prior terrain no longer exists
Two piles sharing a toe One base per pile, both frozen A shared fit tilts toward the larger pile

The scraped-base row is the one that catches monitoring contracts. A prior terrain model is the best base right up until a loader takes fifteen centimetres off the yard while working the pile, after which it is systematically wrong in a direction that inflates the volume. Re-surveying the base whenever the pile is fully cleared — and noting the date in the site config — is the cheap remedy.

Verification snippet

Because the four bases are cheap to evaluate, the strongest verification is to compute all of them and look at the spread. A small spread means the choice does not matter on this pile; a large one means it matters a great deal and the delivered figure needs its assumption stated prominently.

import numpy as np


def base_sensitivity(surface: np.ndarray, mask: np.ndarray, cell: float,
                     bases: dict[str, np.ndarray]) -> dict:
    """Volume under every candidate base, plus the spread between them."""
    vols = {}
    for name, base in bases.items():
        dz = np.where(mask, surface - base, np.nan)
        vols[name] = float(np.nansum(dz) * cell ** 2)

    values = np.array(list(vols.values()))
    spread = float((values.max() - values.min()) / abs(values.mean()))
    verdict = ("base choice is immaterial here" if spread < 0.02
               else "state the base assumption prominently in the deliverable")
    return {"volumes_m3": vols, "relative_spread": spread, "verdict": verdict}

Running this once per site, at the start of a monitoring contract, is twenty seconds of compute that settles an argument before it happens. On a graded yard the spread is often under one percent and the whole question evaporates. On natural ground it is frequently five to eight percent, and knowing that before the first invoice is worth considerably more than the compute.

Base sensitivity on two site types Two grouped bar charts comparing volumes from four base surfaces. On a graded concrete yard the four bars are almost the same height, spanning under one percent, so the base choice is immaterial. On natural undulating ground the same four bases produce bars spanning about nine percent, with the fixed level highest and the fitted plane lowest. A note states that the sensitivity test takes seconds and determines whether the base assumption needs to appear in the deliverable at all. graded yard — spread 0.8 % natural ground — spread 9.1 % plane prior fixed picked plane prior fixed picked The same test answers "does this matter here?" before anyone argues about it. On the left, pick any base. On the right, the base is the deliverable's headline assumption.

Figure 2 — Run the sensitivity once per site. It converts a general worry into a site-specific fact.

A monitoring series with a re-fitted base against a frozen one Two monthly volume series over eight months for a pile that received four deliveries and no removals. The frozen-base series rises in four clean steps and holds flat between them. The re-fitted-base series rises too, but dips between deliveries and shows a false reduction in month five, because the widening pile pushed its own toe onto lower ground and tilted the fitted plane. A note states that the false reduction triggered a stock-loss investigation that found nothing. Jan Feb Mar Apr May Jun Jul Aug volume frozen base — four clean steps false reduction — nothing left the site Freezing the base is not a refinement. It is what makes a monitoring series mean anything.

Figure 3 — The cost of a base that moves. The investigation this triggered cost more than the whole survey programme.

When to escalate

  • The prior terrain model and the current one disagree on bare hardstanding. That is a datum or alignment problem, not a base-surface one, and differencing anything before fixing it will mislead. See aligning two epochs with ICP before differencing.
  • The client’s own figure disagrees and both bases are defensible. The two numbers answer different questions. Put both in the report with their assumptions named rather than negotiating toward a single figure.
  • The pile sits partly outside the survey extent. No base choice fixes missing data. Re-fly with a wider boundary; a volume from a truncated pile is not a volume.

Computing Volumes and Stockpiles in Python