Flagging Overlap and Withheld Points
TL;DR: In LAS 1.4 formats 6–10, overlap and withheld are flag bits, independent of classification. Set them with PDAL (filters.assign with "Overlap = 1 WHERE ..." or "Withheld = 1 WHERE ...") or laspy (las.overlap = mask, las.withheld = mask), keep the point’s real class, and exclude flagged points from density, DTM and statistics with an explicit filter such as Withheld == 0.
# Context and Motivation
This guide is part of ASPRS Classification Codes. Some points should stay in a delivered file but not be used for most purposes. Sidelap returns — from the edge of one swath where the neighbouring swath also covers the ground — double density and often have worse geometry; many workflows prefer one swath’s points in each overlap. Erroneous points that a vendor cannot delete for contractual reasons, such as spikes or points from a mis-calibrated line, need to be kept but ignored. LAS 1.2 handled the first by misusing class 12 and the second with a withheld bit that shared a byte with the class. LAS 1.4 separates both cleanly into flags, so a point can be “ground, but overlap” or “building, but withheld”.
# Prerequisites and Assumptions
- Data in LAS 1.4 point formats 6–10; in formats 0–5 there is no overlap flag (withheld exists but shares a byte with the 5-bit class).
- PDAL 2.x or laspy 2.x.
- A rule for which points are overlap: typically points from a swath outside its “primary” area, or points beyond a scan angle when a neighbouring swath covers the ground.
- For withheld: a documented reason for each withheld set.
# Step-by-Step Implementation
# Step 1 — Decide the overlap rule
A simple, common rule: within a tile, for each ground location covered by several flightlines, keep the line whose nadir is closest and flag the others’ points as overlap. A simpler proxy is scan angle: flag points with |scan angle| above a threshold where sidelap exists.
# Step 2 — Set the overlap flag
With PDAL: filters.assign with "Overlap = 1 WHERE PointSourceId == 1103 && ScanAngleRank > 18". With laspy, assign a boolean mask to las.overlap.
# Step 3 — Withhold erroneous points
Set Withheld = 1 on points that must stay in the file but must not be used — for example, a short block of a flightline with a known timing error.
# Step 4 — Respect flags downstream
Add Withheld == 0 (and Overlap == 0 where appropriate) to the first filter of every pipeline that computes products.
# Step 5 — Document
Record in the delivery metadata what the overlap rule was and why points were withheld.
# Complete Working Example
{
"pipeline": [
"tiles/t_0431.laz",
{ "type": "filters.assign", "value": [
"Overlap = 1 WHERE PointSourceId == 1103 && ScanAngleRank > 18",
"Overlap = 1 WHERE PointSourceId == 1102 && ScanAngleRank < -18",
"Withheld = 1 WHERE PointSourceId == 1104 && GpsTime > 218412500 && GpsTime < 218412560"
]},
{ "type": "writers.las", "filename": "flagged/t_0431.laz",
"minor_version": 4, "dataformat_id": 6, "forward": "all" }
]
}A DTM pipeline that respects both flags:
{
"pipeline": [
"flagged/t_0431.laz",
{ "type": "filters.expression",
"expression": "Withheld == 0 && Overlap == 0 && Classification == 2" },
{ "type": "writers.gdal", "filename": "dtm/t_0431.tif", "resolution": 1.0,
"output_type": "idw", "window_size": 6, "data_type": "float32" }
]
}The same flagging in laspy, with a check of the counts:
import laspy
import numpy as np
las = laspy.read("tiles/t_0431.laz")
psid = np.asarray(las.point_source_id)
angle = np.asarray(las.scan_angle) * 0.006 # PDRF 6+: raw units of 0.006 degrees
las.overlap = (((psid == 1103) & (angle > 18)) | ((psid == 1102) & (angle < -18))).astype(np.uint8)
t = np.asarray(las.gps_time)
las.withheld = ((psid == 1104) & (t > 218_412_500) & (t < 218_412_560)).astype(np.uint8)
las.write("flagged/t_0431.laz")
print(f"overlap {np.mean(las.overlap):.1%}, withheld {int(np.sum(las.withheld)):,} points")# Key Parameter Table
| Flag | PDAL dimension | laspy field | Meaning | Typical use |
|---|---|---|---|---|
| overlap | Overlap |
overlap |
Point lies in sidelap and is not the preferred swath | Density, DTM, uniform products |
| withheld | Withheld |
withheld |
Point should not be used | Errors kept for completeness |
| synthetic | Synthetic |
synthetic |
Point was created, not measured | Breakline or fill points |
| key-point | KeyPoint |
key_point |
Point is a model key point | Thinned surfaces |
# Verification
- Class histogram unchanged. Flagging must not alter classification counts.
- Flag shares plausible. Overlap shares typically run 10–40 percent of points depending on sidelap; withheld points should be a small, explained set.
- Downstream respects flags. Build the DTM with and without the flag filter; differences should appear only where withheld points lay.
# Gotchas and Edge Cases
Scan angle units. In PDRF 6+, the raw scan angle is a 16-bit integer in 0.006° steps; PDAL exposes it in degrees as ScanAngleRank, laspy’s scan_angle field holds raw units. Convert before thresholding in laspy, as the example does.
Old class 12. Data upgraded from LAS 1.2 may still use class 12 for overlap. Convert it to the flag, as in upgrading LAS 1.2 files to LAS 1.4.
Tools that ignore flags. Not every tool honours withheld and overlap. Filter explicitly in your own pipelines rather than assuming a consumer does.
Overlap and accuracy. Overlap points are exactly what swath-to-swath relative accuracy compares. Keep them in the file even when products exclude them; see measuring swath-to-swath relative accuracy.
# Frequently Asked Questions
What is the overlap flag in LAS 1.4?
A bit in the classification flags byte of point formats 6 to 10 that marks points in sidelap areas which are not from the preferred swath. It replaces the older practice of assigning class 12 to overlap points, so the real class is preserved.
What does withheld mean?
A withheld point should be excluded from processing and products, but remains in the file. It is used for erroneous points that are retained for completeness or contractual reasons.
How do I exclude withheld points in PDAL?
Add an expression filter with Withheld equal to 0 at the start of the pipeline, or include the condition in the where clause of the stages that should ignore them.
Can a point be both ground and overlap?
Yes. In LAS 1.4, classification and flags are independent. A point can be ground, building or any other class and also carry the overlap or withheld flag.
# Related
- ASPRS Classification Codes — classes and their meaning
- Counting Points per Class with PDAL — histograms including flags
- Understanding LAS Point Data Record Formats — where flags live
- Checking Pulse Spacing Against USGS Quality Levels — density with and without overlap
- Assigning Classification with Conditional filters.assign — the assignment syntax