---
title: "What is LiDAR Data? How It Works, Formats, and Sources"
url: "https://wherobots.com/discover/lidar-data/"
description: "LiDAR data is a 3D point cloud from laser pulses that maps ground, trees, and buildings. How it works, LAS and COPC formats, USGS 3DEP downloads, and uses."
published: "2026-09-30"
modified: "2026-10-21"
---

# What is LiDAR Data? How It Works, Formats, and Sources

LiDAR (light detection and ranging) data is a set of 3D points measured by a laser scanner, which times each light pulse's round trip to a surface. Each point carries x, y, and z coordinates, the echo's strength (intensity), its order (return number), and a class code such as ground, vegetation, building, or water. Airborne LiDAR data maps terrain, tree canopy, and buildings over whole regions. The [U.S. Geological Survey (USGS) describes LiDAR data](https://www.usgs.gov/faqs/what-lidar-data-and-where-can-i-download-it) as the basis for elevation models with a vertical accuracy of about 10 cm. This article tests one claim with Portland data. The claim is that a 30 m radar map of the surface, minus the LiDAR ground height, gives the mean height of a forest and fails on towers.

## Key takeaways

- LiDAR times laser pulses to measure distance. Satellite positioning and a motion sensor place each measurement on the map.
- One pulse can return several echoes, from canopy top to ground, so LiDAR maps terrain under forest.
- LiDAR data is stored as LAS, compressed as LAZ, and streamed as Cloud Optimized Point Cloud (COPC) files. Each point carries a standard class code.
- The main derived products are digital terrain models (DTM) and digital surface models (DSM), canopy height models (CHM) computed as DSM − DTM, and building heights.
- The USGS 3D Elevation Program publishes free LiDAR data for the United States at quality levels 1 and 2 (QL1 and QL2).

## What LiDAR data is

The National Oceanic and Atmospheric Administration (NOAA) defines LiDAR as [a remote sensing method that uses light in the form of a pulsed laser](https://oceanservice.noaa.gov/facts/lidar.html) to measure ranges to the Earth. The range is half the round-trip time multiplied by the speed of light. Each measurement becomes one point.

The raw product is a point cloud: a loose set of points, with no grid and no lines between them. One survey samples every surface the pulses reached: ground, trees, roofs, power lines, and parked cars. Photogrammetry also builds point clouds, from overlapping photographs. LiDAR data adds several returns per pulse, which reach the ground through gaps in a canopy.

## How LiDAR works

The laser scanner measures the range and angle of each pulse. A GNSS (Global Navigation Satellite System) receiver records the scanner's position by satellite, and an inertial measurement unit records its roll, pitch, and heading. Wehr and Lohr laid out these components and the positioning math in [Airborne laser scanning: an introduction and overview](https://doi.org/10.1016/S0924-2716%2899%2900011-8) (1999). In [NOAA's description](https://oceanservice.noaa.gov/facts/lidar.html), topographic LiDAR uses near-infrared light to map land, and bathymetric LiDAR uses green light that penetrates water to map riverbeds and the seafloor.

![Diagram of one airborne LiDAR pulse passing through a tree. Four yellow points mark the first return at the canopy top, two returns inside the crown, and the last return on the ground. A second pulse returns once from a building roof labeled class 6. A dashed pink line traces the surface model over the canopy and roof, a gray line traces the ground, and an arrow marks canopy height as DSM minus DTM. A side panel shows the full waveform with four energy peaks at the same heights](https://wherobots.com/wp-content/themes/wherobots/assets/img/discover/lidar-data-pulse-returns.webp)

*One pulse, several returns. Discrete-return sensors keep the peaks as points; full-waveform sensors such as GEDI (Global Ecosystem Dynamics Investigation) record the whole returned signal. Ground returns build the terrain model and first returns build the surface model.*

**Returns.** A pulse spreads into a footprint, so part of the beam hits the canopy top, part hits branches, and part reaches the ground.

**Discrete return vs full waveform.** Most survey sensors record discrete returns, a few peaks per pulse. Full-waveform sensors record the whole returned signal, including the structure between peaks. Mallet and Bretar reviewed the method in [Full-waveform topographic lidar: state-of-the-art](https://doi.org/10.1016/j.isprsjprs.2008.09.007) (2009).

**Point density.** Density sets what a survey can resolve. The USGS [quality levels](https://www.usgs.gov/3d-elevation-program/topographic-data-quality-levels-qls) require at least 2 pulses per square meter for QL2 and at least 8 for QL1. Both require 10 cm vertical accuracy on open ground, measured as RMSEz, the root mean square error of heights. A QL1 survey resolves roof planes and individual crowns that QL2 blurs.

### Airborne, terrestrial, mobile, and spaceborne LiDAR

| Platform | Typical carrier | What it covers |
| --- | --- | --- |
| Airborne laser scanning (ALS) | Aircraft, helicopter, drone | Regional terrain, forests, cities; the source of 3DEP and most national programs |
| Terrestrial laser scanning (TLS) | Tripod | Building facades, bridges, mines, and forest plots at high density |
| Mobile laser scanning (MLS) | Car, train, backpack | Road and rail corridors, street furniture, utility poles |
| Spaceborne | Satellite, space station | Global samples of ice, forest height, and terrain along orbit tracks |

NASA's [ICESat-2](https://icesat-2.gsfc.nasa.gov/) launched in September 2018. Its ATLAS (Advanced Topographic Laser Altimeter System) laser fires 10,000 times a second at 532 nm across six beams and counts single photons. Markus and colleagues set out its design in [The Ice, Cloud, and land Elevation Satellite-2 (ICESat-2): science requirements, concept, and implementation](https://doi.org/10.1016/j.rse.2016.12.029) (2017). [GEDI](https://gedi.umd.edu/) was installed on the International Space Station in December 2018. Its three full-waveform lasers produce eight ground tracks of 25 m footprints. Dubayah and colleagues described it in [The Global Ecosystem Dynamics Investigation: high-resolution laser ranging of the Earth's forests and topography](https://doi.org/10.1016/j.srs.2020.100002) (2020).

## LiDAR data formats LAS, LAZ, and COPC

LAS is the binary exchange format for point clouds. It is owned by the American Society for Photogrammetry and Remote Sensing (ASPRS) and [maintained in the open](https://github.com/ASPRSorg/LAS). The Open Geospatial Consortium (OGC) has recognized LAS as a [community standard](https://www.ogc.org/publications/standard/las/) since 2018. Each point record holds x, y, z, intensity, return number, number of returns, scan angle, GPS time, and a classification code. LAS 1.5, approved in August 2025, drops the legacy point formats 0 to 5 and keeps formats 6 to 10.

LAZ is LAS with lossless compression. Martin Isenburg's [LASzip](https://doi.org/10.14358/PERS.79.2.209) (2013) produces files 7 to 25 percent of the original size. [Cloud Optimized Point Cloud (COPC)](https://copc.io/) is a LAZ 1.4 file with its points sorted into nested cubes (an octree) and an index of where each cube sits. A client can download one area or level of detail over HTTP without the whole file.

### LiDAR classification codes

The LAS specification defines the [ASPRS standard point classes](https://github.com/ASPRSorg/LAS). These are the values for point formats 6 to 10:

| Code | Class | Code | Class |
| --- | --- | --- | --- |
| 0 | Created, never classified | 11 | Road surface |
| 1 | Unclassified | 13 | Wire, guard (shield) |
| 2 | Ground | 14 | Wire, conductor (phase) |
| 3 | Low vegetation | 15 | Transmission tower |
| 4 | Medium vegetation | 16 | Wire-structure connector |
| 5 | High vegetation | 17 | Bridge deck |
| 6 | Building | 18 | High noise |
| 7 | Low point (noise) | 19 | Overhead structure |
| 9 | Water | 20 | Ignored ground |
| 10 | Rail | 21, 22 | Snow, temporal exclusion |

Codes 8 and 12 and the range 23 to 63 are reserved, and 64 to 255 are free for user definitions.

## From point cloud to DEM, DSM, CHM, and building heights

Most analysts use LiDAR data after it is gridded into rasters, usually [GeoTIFF](https://wherobots.com/discover/geotiff/):

- **Digital terrain model (DTM).** Ground points (class 2) are interpolated into a bare-earth grid, the [digital elevation model](https://wherobots.com/discover/digital-elevation-model/) that 3DEP publishes at 1 m.
- **Digital surface model (DSM).** The highest or first returns are gridded into a surface that includes canopy and roofs.
- **Canopy height model (CHM).** The DSM minus the DTM gives the height of everything above ground. The National Ecological Observatory Network (NEON) builds its [1 m CHM product](https://data.neonscience.org/data-products/DP3.30015.001) this way.
- **Building heights.** Building points (class 6) inside a footprint, minus the ground under it, give roof height. The [Overture Maps Foundation](https://openstreetmap.us/events/state-of-the-map-us/2023/building-heights-from-open-usgs-lidar-to-open-overture-maps/) estimated heights for millions of US buildings from 3DEP LiDAR and published them under an open license.

## Where to download LiDAR data

The main public LiDAR archives are free:

- **USGS 3DEP.** The [3D Elevation Program](https://www.usgs.gov/3d-elevation-program) collects LiDAR across the United States to the [Lidar Base Specification](https://www.usgs.gov/ngp-standards-and-specifications/lidar-base-specification-collection-requirements). The [LidarExplorer](https://apps.nationalmap.gov/lidar-explorer/) map shows coverage and serves point clouds as LAZ tiles and the 1 m DEMs made from them. The point clouds are also an [AWS open dataset](https://registry.opendata.aws/usgs-lidar/). LAZ tiles sit in a requester-pays bucket (the downloader pays transfer costs), and Entwine Point Tiles, a streamable octree format, sit in a public one.
- **NOAA.** The [Data Access Viewer](https://coast.noaa.gov/dataviewer/) serves NOAA's coastal topographic and bathymetric LiDAR.
- **OpenTopography.** A facility at the San Diego Supercomputer Center, funded by the National Science Foundation (NSF), hosts and processes academic and agency surveys worldwide on request. Krishnan and colleagues described the design in [OpenTopography: a services oriented architecture for community access to LIDAR topography](https://doi.org/10.1145/1999320.1999327) (2011).
- **National programs.** The Netherlands publishes its national elevation dataset, Actueel Hoogtebestand Nederland ([AHN](https://www.ahn.nl/open-data)), as open data. England's Environment Agency publishes its [National LIDAR Programme](https://www.data.gov.uk/dataset/f0db0249-f17b-4036-9e65-309148c97ce4/national-lidar-programme) at 1 m.

## LiDAR data examples

- **National elevation.** 3DEP's 1 m bare-earth DEMs supply terrain for flood models and [flood risk data](https://wherobots.com/discover/flood-risk-data/), where a small change in ground height changes which buildings flood.
- **Global forest structure.** GEDI waveforms measure canopy height and vertical structure, which its science team uses to estimate forest biomass and its change.
- **Ice and sea ice.** ICESat-2 measures elevation change of glaciers and ice sheets and the thickness distribution of sea ice.
- **Building heights for maps.** The same Overture project reported that fewer than 20 percent of US OpenStreetMap buildings carried a height tag. Overture's LiDAR-derived heights address that gap.
- **Utilities and transport.** The ASPRS classes for rail, wires, and towers (10 and 13 to 15) let utilities and railways map corridors and the vegetation near them.

## LiDAR data in Wherobots

WherobotsDB reads LiDAR-derived rasters directly and queries LiDAR points as tables.

**Derived rasters.** 3DEP publishes its 1 m DEMs as Cloud Optimized GeoTIFFs in a public bucket, and [RS_FromPath](https://docs.wherobots.com/reference/wherobots-db/raster-data/constructors/RS_FromPath) opens them as out-db rasters. The file stays in the bucket, and a query reads only the tiles it needs:

```
SELECT RS_MetaData(r) AS md, RS_BandPixelType(r) AS pt, RS_BandNoDataValue(r) AS nd, RS_SRID(r) AS srid
FROM (SELECT RS_FromPath('s3://prd-tnm/StagedProducts/Elevation/1m/Projects/OR_PortlandMetro_B24/TIFF/USGS_1M_10_x52y505_OR_PortlandMetro_B24.tif') AS r)
```

The tile from the 2024 Portland Metro survey holds 10,012 by 10,012 pixels of 1 m heights, stored as 32-bit floating-point numbers (float32). Its spatial reference identifier (SRID) is 26910, which is NAD83 (North American Datum of 1983) on Universal Transverse Mercator (UTM) zone 10N. It uses 512-pixel internal tiles, and −999999 marks missing values (NoData). A canopy height model or DSM stored as GeoTIFF loads the same way. [RS_MapAlgebra](https://docs.wherobots.com/reference/wherobots-db/raster-data/map-algebra-operators/RS_MapAlgebra) subtracts one from the other in a single statement.

**Point tables.** The Wherobots documentation lists no LAS or LAZ reader, so point clouds are converted first. The Point Data Abstraction Library (PDAL) has an [Arrow writer](https://pdal.io/en/stable/stages/writers.arrow.html) that writes LAS points to GeoParquet, one row per point. That file loads as a [Havasu table](https://docs.wherobots.com/reference/havasu-table/introduction), the WherobotsDB table format, with an [ST_PointZ](https://docs.wherobots.com/reference/wherobots-db/geometry-data/constructors/ST_PointZ) geometry for each point. [ST_3DDWithin](https://docs.wherobots.com/reference/wherobots-db/geometry-data/predicates/ST_3DDWithin) and [ST_3DDistance](https://docs.wherobots.com/reference/wherobots-db/geometry-data/measurement/ST_3DDistance) then find points within a 3D distance of each other. A [spatial join](https://wherobots.com/discover/spatial-join/) with [ST_Intersects](https://docs.wherobots.com/reference/wherobots-db/geometry-data/predicates/ST_Intersects) assigns every point to a parcel or [building footprint](https://wherobots.com/discover/building-footprint/).

The walkthrough uses Portland, Oregon, where these sources overlap:

| Layer | Source in the query | Sensor | Grid | Format | What the queries read |
| --- | --- | --- | --- | --- | --- |
| Ground (DTM) | 3DEP 1 m DEM, `OR_PortlandMetro_B24` | Airborne LiDAR, 2024 | 1 m, North American Vertical Datum of 1988 (NAVD88) heights | Cloud Optimized GeoTIFF files on S3; tile `x52y505` is 10,012 by 10,012 pixels | Two tiles, `x52y504` and `x52y505`, in both queries |
| Surface (DSM) | [Copernicus DEM GLO-30](https://wherobots.com/havasu/#glo_30m) | TanDEM-X X-band radar, 2011 to 2015 | 1 arc-second, about 30 m, Earth Gravitational Model 2008 (EGM2008) heights | Havasu raster table | One tile in each query |
| Canopy (CHM) | [Meta and WRI CHMv2](https://wherobots.com/havasu/#global_v2) | Optical imagery, model trained on airborne LiDAR | About 1 m, heights in meters | Havasu raster table | Two tiles that cover the four zones (forest query only) |
| Zones | [Overture land use](https://wherobots.com/havasu/#base_land_use) | Map data | Polygons | Havasu vector table | Four named polygons (forest query only) |
| Buildings | [Overture buildings](https://wherobots.com/havasu/#buildings_building) | Map data | Polygons with a height attribute | Havasu vector table | Footprints of 2,000 m² or more with a height inside a 2 km box over downtown Portland; 117 in the result (building query only) |

WherobotsDB reads the rasters and the vector polygons in one SQL statement; most stacks pick one data model.

The [Copernicus DEM](https://dataspace.copernicus.eu/sites/default/files/media/files/2024-06/geo1988-copernicusdem-spe-002_producthandbook_i5.0.pdf) is a surface model that includes trees and buildings. Surface minus ground measures how much height a 30 m radar model records over forest and towers.

### Forest height from radar surface minus LiDAR ground

The first query takes four [Overture land use](https://wherobots.com/havasu/#base_land_use) polygons: three forested parks in the West Hills and the Albina rail yard as open ground. It computes the mean of each raster inside each polygon, a zonal statistic. [RS_ZonalStatsAll](https://docs.wherobots.com/reference/wherobots-db/raster-data/band-accessors/RS_ZonalStatsAll) returns the sum and count of pixels per raster tile, so a zone spanning several tiles is weighted by its pixels in each.

```
-- Lidar ground, radar surface, and lidar-trained canopy height for four Portland zones
WITH zones AS (
  SELECT names.primary AS zone, ST_SetSRID(geometry, 4326) AS geom,
         ST_AreaSpheroid(geometry) / 10000 AS ha
  FROM wherobots_open_data.overture_maps_foundation.base_land_use
  WHERE bbox.xmax > -122.76 AND bbox.xmin < -122.66 AND bbox.ymax > 45.48 AND bbox.ymin < 45.56
    AND names.primary IN ('Washington Park', 'Hoyt Arboretum', 'Marquam Nature Park', 'Albina Yard')
),
dtm AS (
  -- USGS 3DEP 1 m bare-earth DEM from the 2024 Portland Metro lidar survey (NAD83 / UTM 10N, NAVD88)
  SELECT RS_FromPath(concat('s3://prd-tnm/StagedProducts/Elevation/1m/Projects/OR_PortlandMetro_B24/TIFF/USGS_1M_10_',
                            t, '_OR_PortlandMetro_B24.tif')) AS rast
  FROM VALUES ('x52y504'), ('x52y505') AS v(t)
),
ground AS (
  SELECT /*+ BROADCAST(d) */ z.zone, RS_ZonalStatsAll(d.rast, z.geom, 1, false, true) AS s
  FROM zones z CROSS JOIN dtm d
),
surface AS (
  -- Copernicus GLO-30, a radar digital surface model (EGM2008 heights)
  SELECT z.zone, RS_ZonalStatsAll(c.rast, z.geom, 1, false, true) AS s
  FROM zones z JOIN wherobots_open_data.copernicus_dem.glo_30m c ON ST_Intersects(c.footprint, z.geom)
),
canopy AS (
  -- Meta and WRI canopy height model, metres, trained on airborne lidar
  SELECT z.zone, RS_ZonalStatsAll(m.rast, z.geom, 1, false, true) AS s
  FROM zones z JOIN wherobots_open_data.meta_canopy_height.global_v2 m ON ST_Intersects(m.footprint, z.geom)
),
agg AS (
  SELECT 'ground' AS layer, zone, SUM(s.sum) AS total, SUM(s.count) AS n, MAX(s.max) AS mx FROM ground WHERE s.count > 0 GROUP BY zone
  UNION ALL
  SELECT 'surface', zone, SUM(s.sum), SUM(s.count), MAX(s.max) FROM surface WHERE s.count > 0 GROUP BY zone
  UNION ALL
  SELECT 'canopy', zone, SUM(s.sum), SUM(s.count), MAX(s.max) FROM canopy WHERE s.count > 0 GROUP BY zone
)
SELECT z.zone, ROUND(z.ha, 1) AS ha,
       ROUND(MAX(CASE WHEN layer = 'ground'  THEN total / n END), 2) AS lidar_ground_m,
       ROUND(MAX(CASE WHEN layer = 'surface' THEN total / n END), 2) AS radar_surface_m,
       ROUND(MAX(CASE WHEN layer = 'surface' THEN total / n END) - MAX(CASE WHEN layer = 'ground' THEN total / n END), 2) AS surface_minus_ground_m,
       ROUND(MAX(CASE WHEN layer = 'canopy'  THEN total / n END), 2) AS mean_canopy_m,
       MAX(CASE WHEN layer = 'canopy' THEN mx END) AS max_canopy_m,
       MAX(CASE WHEN layer = 'ground' THEN n END) AS ground_px,
       MAX(CASE WHEN layer = 'surface' THEN n END) AS surface_px,
       MAX(CASE WHEN layer = 'canopy' THEN n END) AS canopy_px
FROM zones z JOIN agg a ON a.zone = z.zone
GROUP BY z.zone, z.ha
ORDER BY mean_canopy_m DESC
```

It ran in 144 seconds. Washington Park holds 1,963,217 LiDAR ground pixels and 2,935 radar pixels.

| Zone | Area | LiDAR ground | Radar surface | Surface − ground | Canopy model mean | Canopy model max |
| --- | --- | --- | --- | --- | --- | --- |
| Marquam Nature Park | 83.7 ha | 180.28 m | 203.88 m | 23.60 m | 22.80 m | 49 m |
| Washington Park | 194.9 ha | 182.53 m | 196.76 m | 14.22 m | 14.55 m | 50 m |
| Hoyt Arboretum | 65.1 ha | 227.66 m | 240.19 m | 12.52 m | 14.38 m | 50 m |
| Albina Yard | 85.0 ha | 10.54 m | 9.59 m | −0.95 m | 0.03 m | 23 m |

![Paired horizontal bar chart for four Portland zones. Marquam Nature Park: canopy model mean 22.80 m, radar surface minus lidar ground 23.60 m. Washington Park: 14.55 m and 14.22 m. Hoyt Arboretum: 14.38 m and 12.52 m. Albina rail yard: 0.03 m and minus 0.95 m](https://wherobots.com/wp-content/themes/wherobots/assets/img/discover/lidar-data-portland-canopy-zones.webp)

*Mean height above 3DEP LiDAR ground in four Portland zones. Over forest, Copernicus GLO-30 minus the LiDAR ground lands within 1.9 m of the CHMv2 canopy mean; over the open rail yard it reads −0.95 m.*

Over the forested parks, radar surface minus LiDAR ground lands within 0.3 to 1.9 m of the canopy model's mean. Together, a 30 m surface model and a 1 m LiDAR terrain model give a forest's average height. They miss the tallest conifers, 49 to 50 m in the canopy model, which a 30 m cell averages with lower trees. The rail yard, with almost no canopy, reads −0.95 m. That baseline combines radar noise with the gap between two [vertical datums](https://wherobots.com/discover/coordinate-reference-system/), the reference surfaces that heights are measured from: NAVD88 for 3DEP and EGM2008 for GLO-30.

### Building heights from radar surface minus LiDAR ground

The second query repeats the subtraction for the downtown buildings listed in the sources table. It groups buildings by the source of their Overture height: USGS LiDAR, OpenStreetMap, or Microsoft's machine-learning heights. It compares each height with the highest radar pixel in the footprint minus the mean LiDAR ground under it. Each raster is clipped once to the box and copied to every worker, so each building reads two small rasters in memory. The query ran in 142 seconds.

```
-- Radar surface minus lidar ground at downtown Portland buildings, by Overture height source
WITH aoi AS (
  SELECT ST_SetSRID(ST_PolygonFromEnvelope(-122.695, 45.514, -122.670, 45.532), 4326) AS box
),
b AS (
  -- Footprints of 2,000 m2 or more with a height, fully inside the box
  SELECT id, height,
         CASE WHEN exists(sources, s -> s.dataset = 'USGS Lidar') THEN 'USGS Lidar'
              WHEN exists(sources, s -> s.property = '/properties/height'
                                        AND s.dataset = 'Microsoft ML Buildings') THEN 'Microsoft ML'
              ELSE 'OpenStreetMap' END AS height_source,
         ST_SetSRID(geometry, 4326) AS geom
  FROM wherobots_open_data.overture_maps_foundation.buildings_building
  WHERE bbox.xmin > -122.695 AND bbox.xmax < -122.670 AND bbox.ymin > 45.514 AND bbox.ymax < 45.532
    AND height IS NOT NULL AND ST_AreaSpheroid(geometry) >= 2000
),
-- Clip each raster once to the box. RS_Clip(raster, band, geom, allTouched, noDataValue, crop)
dtm AS (
  -- USGS 3DEP 1 m bare-earth DEM from the 2024 Portland Metro lidar survey (NAVD88 heights)
  SELECT /*+ BROADCAST(a) */ RS_Clip(RS_FromPath(concat(
           's3://prd-tnm/StagedProducts/Elevation/1m/Projects/OR_PortlandMetro_B24/TIFF/USGS_1M_10_',
           v.t, '_OR_PortlandMetro_B24.tif')), 1, a.box, true, -999999, true) AS rast
  FROM VALUES ('x52y504'), ('x52y505') AS v(t) CROSS JOIN aoi a
),
dsm AS (
  -- Copernicus DEM GLO-30, a radar digital surface model (EGM2008 heights)
  SELECT /*+ BROADCAST(a) */ RS_Clip(c.rast, 1, a.box, true, -32767, true) AS rast
  FROM wherobots_open_data.copernicus_dem.glo_30m c JOIN aoi a ON ST_Intersects(c.footprint, a.box)
),
zs AS (
  -- Zonal statistics per building on the small clipped rasters, broadcast to every partition
  SELECT /*+ BROADCAST(d) */ 'ground' AS layer, b.id, RS_ZonalStatsAll(d.rast, b.geom, 1, false, true) AS s
  FROM b CROSS JOIN (SELECT rast FROM dtm WHERE rast IS NOT NULL) d
  UNION ALL
  SELECT /*+ BROADCAST(d) */ 'surface', b.id, RS_ZonalStatsAll(d.rast, b.geom, 1, false, true)
  FROM b CROSS JOIN (SELECT rast FROM dsm WHERE rast IS NOT NULL) d
),
per_building AS (
  -- Highest radar surface pixel in the footprint minus the mean lidar ground under it
  SELECT b.id, b.height_source, b.height AS overture_height_m,
         MAX(CASE WHEN z.layer = 'surface' THEN z.s.max END)
           - SUM(CASE WHEN z.layer = 'ground' THEN z.s.sum END)
             / SUM(CASE WHEN z.layer = 'ground' THEN z.s.count END) AS radar_minus_ground_m
  FROM b JOIN zs z ON z.id = b.id
  WHERE z.s.count > 0
  GROUP BY b.id, b.height_source, b.height
)
-- One row per height source plus an all-buildings row (height_source is NULL).
-- SELECT * FROM per_building returns each building.
SELECT height_source, COUNT(*) AS buildings,
       ROUND(corr(overture_height_m, radar_minus_ground_m), 2) AS r,
       ROUND(percentile(overture_height_m, 0.5), 1) AS median_overture_m,
       ROUND(percentile(radar_minus_ground_m - overture_height_m, 0.5), 1) AS median_gap_m,
       COUNT_IF(overture_height_m >= 100) AS towers_100m,
       ROUND(percentile(CASE WHEN overture_height_m >= 100 THEN radar_minus_ground_m END, 0.5), 1) AS towers_radar_m
FROM per_building
WHERE radar_minus_ground_m IS NOT NULL
GROUP BY GROUPING SETS ((height_source), ())
ORDER BY buildings DESC
```

It returned 117 buildings:

| Overture height source | Buildings | Median Overture height | Correlation (r) | Median gap, radar minus Overture |
| --- | --- | --- | --- | --- |
| USGS Lidar | 49 | 15.2 m | 0.55 | −4.8 m |
| Microsoft ML | 34 | 15.7 m | 0.08 | −4.3 m |
| OpenStreetMap | 34 | 71.5 m | 0.04 | −56.8 m |
| All buildings | 117 | 18.5 m | 0.22 | −8.0 m |

![Scatter plot of 117 downtown Portland buildings. The horizontal axis is Overture height from 0 to 175 m, and the vertical axis is Copernicus GLO-30 surface minus 3DEP LiDAR ground. Green points for buildings with USGS LiDAR heights cluster near the one-to-one line at low heights. Pink points for OpenStreetMap heights include every tower but stay low on the vertical axis. The tallest tower, 167 m in Overture, reads 8.0 m](https://wherobots.com/wp-content/themes/wherobots/assets/img/discover/lidar-data-portland-building-heights.webp)

*Highest GLO-30 pixel minus mean 3DEP LiDAR ground for 117 Overture buildings in downtown Portland. Buildings with USGS LiDAR heights track the radar surface (r = 0.55); the six towers of 100 m or more read a median 10.8 m.*

For low and mid-rise buildings whose Overture height came from USGS LiDAR, the radar surface tracks the height (r = 0.55). It sits a median 4.8 m low, consistent with 30 m cells that mix roofs with streets. The method fails on towers. A tower covers one or two 30 m cells. [Synthetic aperture radar](https://wherobots.com/discover/synthetic-aperture-radar/) looks at the ground from the side, so tall facades are shifted in the image and hide what is behind them. The six towers of 100 m or more, all with OpenStreetMap heights, read a median 10.8 m above the LiDAR ground. The 34 Microsoft machine-learning (ML) heights, median 15.7 m, correlate little with the radar surface (r = 0.08). Overture's LiDAR-sourced heights came from 3DEP point clouds.

The same SQL runs per 3DEP tile across a county or a state. The Model Context Protocol (MCP) is a standard way to connect an AI agent to tools and data. An agent connected through the [Wherobots MCP Server](https://docs.wherobots.com/develop/mcp/mcp-server-overview) can write it from a plain-language request. The models people use every day were trained on text, documents, databases, and the internet. Spatial SQL over elevation rasters and footprints gives those models measured heights of real places, the basis of [geospatial AI](https://wherobots.com/discover/geospatial-ai/). Where no LiDAR survey exists, RasterFlow's [Meta CHM v1 model](https://docs.wherobots.com/tutorials/example-notebooks/rasterflow-chm) estimates canopy height in meters from 60 cm aerial imagery. The imagery comes from the National Agriculture Imagery Program (NAIP), and the output is a raster that the same RS\_ functions read.

## LiDAR research and what changes at scale

### From ranging to mapping

After Wehr and Lohr's 1999 system overview, forestry led the applications. Lefsky, Cohen, Parker, and Harding showed in [Lidar remote sensing for ecosystem studies](https://doi.org/10.1641/0006-3568%282002%29052%5B0019:LRSFES%5D2.0.CO;2) (2002) that LiDAR measures canopy structure directly. Næsset's [two-stage procedure](https://doi.org/10.1016/S0034-4257%2801%2900290-5) (2002) introduced the area-based approach that forest management inventories use. A regression links tree measurements in field plots to LiDAR height statistics, then predicts every cell of the survey. Popescu, Wynne, and Nelson [measured individual crown diameter](https://doi.org/10.5589/m03-027) (2003) to estimate tree volume and biomass. Khosravipour and colleagues removed a common artifact, false holes in the canopy surface, with [pit-free canopy height models](https://doi.org/10.14358/PERS.80.9.863) (2014).

### Ground filtering

Every DTM depends on separating ground returns from everything else. Axelsson's [adaptive TIN (triangulated irregular network) densification](https://www.isprs.org/proceedings/xxxiii/congress/part4/111_xxxiii-part4.pdf) (2000) builds a coarse triangle surface from the lowest local points. It adds points within angle and distance limits and rebuilds the surface each pass. Zhang, Chen, Whitman, and colleagues introduced the [progressive morphological filter](https://doi.org/10.1109/TGRS.2003.810682) (2003). It removes cars, trees, and buildings with a minimum then maximum filter (an opening) whose window grows step by step. Sithole and Vosselman's [experimental comparison of eight filters](https://doi.org/10.1016/j.isprsjprs.2004.05.004) (2004) found that all did well on smooth rural terrain and all made errors in complex cities and on rough, vegetated slopes. Zhang, Qi, Wan, and colleagues then proposed the [cloth simulation filter](https://doi.org/10.3390/rs8060501) (2016). It turns the point cloud upside down, drops a simulated cloth on it, and keeps the points the cloth touches. It needs few parameters and ships as a plugin in the open-source CloudCompare.

### Deep learning on point clouds

Point clouds have no grid, so early networks voxelized or rendered them first. Qi, Su, Mo, and Guibas removed that step with [PointNet](https://doi.org/10.1109/CVPR.2017.16) (CVPR 2017), a network that reads raw points in any order. [PointNet++](https://proceedings.neurips.cc/paper/2017/hash/d8bf84be3800d12f74d8b05e9b89836f-Abstract.html) (NeurIPS 2017) added groups of nearby points at several scales. Thomas and colleagues' Kernel Point Convolution, [KPConv](https://doi.org/10.1109/ICCV.2019.00651) (ICCV 2019), placed convolution kernels at points in space. [Semantic3D](https://doi.org/10.5194/isprs-annals-IV-1-W1-91-2017) (Hackel and colleagues, 2017) released over four billion hand-labeled terrestrial LiDAR points in eight classes. Guo and colleagues' [survey of deep learning for 3D point clouds](https://doi.org/10.1109/TPAMI.2020.3005434) (2021) reviews the work that followed.

### Spaceborne LiDAR and global canopy height

Airborne surveys are dense and local; spaceborne LiDAR is global and sparse. ICESat-2's land and vegetation product reports ground and canopy heights in 100 m segments along track. Neuenschwander and Pitts describe it in [The ATL08 land and vegetation product for the ICESat-2 Mission](https://doi.org/10.1016/j.rse.2018.11.005) (2019). GEDI samples canopy height in 25 m footprints. Potapov and colleagues [extrapolated GEDI with Landsat](https://doi.org/10.1016/j.rse.2020.112165) to a 30 m global forest height map for 2019 (2021). Lang, Jetz, Schindler, and Wegner trained a deep network on GEDI and Sentinel-2 for [a high-resolution canopy height model of the Earth](https://doi.org/10.1038/s41559-023-02206-6) at 10 m (2023). Tolan and colleagues reached 1 m with [canopy height maps from Maxar RGB imagery](https://doi.org/10.1016/j.rse.2023.113888) (2024), imagery in red, green, and blue bands. Their vision transformer, trained on aerial LiDAR and calibrated with GEDI, had a reported mean absolute error of 2.8 m. Brandt and colleagues' [CHMv2](https://doi.org/10.1038/s41597-026-07882-0) (2026) rebuilt the model on the DINOv3 image network. They validated it against independent airborne LiDAR and against GEDI and ICESat-2 observations. It is the canopy layer in the Portland queries.

### What changes at scale

A 1,000 km² county at the QL1 minimum of 8 pulses per square meter is 8 billion pulses. The 3DEP archive on AWS held [more than 12 trillion points](https://www.usgs.gov/news/technical-announcement/usgs-3dep-lidar-point-cloud-now-available-amazon-public-dataset) when USGS announced it. Stoker and Miller tested whether data from many producers are [accurate and consistent across 3DEP](https://doi.org/10.3390/rs14040940) (2022). At that scale, analysis needs many machines working in parallel. Jia Yu, Jinxuan Wu, and Mohamed Sarwat introduced spatial processing on Apache Spark with [GeoSpark](https://doi.org/10.1145/2820783.2820860) (ACM SIGSPATIAL 2015). Yu, Zhang, and Sarwat described its partitioning, indexing, and join design in [Spatial data management in Apache Spark: the GeoSpark perspective and beyond](https://doi.org/10.1007/s10707-018-0330-9) (GeoInformatica, 2019). GeoSpark became Apache Sedona. Its raster functions run the zonal statistics in the queries above in parallel. [Raster processing at scale: the out-of-database architecture behind WherobotsDB](https://wherobots.com/blog/raster-processing-at-scale-out-of-database-architecture-wherobotsdb/) explains why a zonal statistic reads only the Cloud Optimized GeoTIFF (COG) tiles under each zone.

### Open problems

- **Ground under dense canopy and on steep slopes.** Few pulses reach the ground in closed forest, and filters confuse slope breaks with objects.
- **Time.** Surveys capture one date. In Portland the LiDAR ground is from 2024, the radar surface from 2011 to 2015, and the canopy imagery from varying dates. A building completed after 2015 has LiDAR ground but no radar height.
- **Datums.** Mixing products means mixing vertical datums, as in the −0.95 m rail yard baseline.
- **Labels.** Deep networks need labeled points, and labeled airborne data is scarce outside a few benchmarks.
- **Points in databases.** Point clouds still ship as files and need conversion to tables before SQL beside rasters and vectors.

## Conclusions

1. LiDAR terrain, canopy, and building heights all start from the points labeled ground. Every filter in Sithole and Vosselman's comparison made errors in complex cities and on rough, vegetated slopes. Check how the ground class was made before trusting a 1 m DEM there.
2. For mean forest height, LiDAR ground plus a 30 m radar surface model can stand in for a LiDAR surface model. Over three Portland parks the difference landed within 0.3 to 1.9 m of the canopy model's mean. The tallest trees, 49 to 50 m, average out in 30 m cells.
3. Building heights in a city need LiDAR data or a meter-scale surface model. The 49 downtown buildings with USGS LiDAR heights tracked the 30 m radar surface at r = 0.55, a median 4.8 m low. The six towers of 100 m or more read a median 10.8 m.
4. Before subtracting a LiDAR ground from another product, match the vertical datums and the dates. The −0.95 m rail yard baseline combines the NAVD88 to EGM2008 datum gap with radar noise. A 2024 LiDAR ground under a 2011 to 2015 radar surface gives newer buildings no height.
5. Rasters made from LiDAR data can be queried in place; LiDAR points need conversion first. Clip each raster once to the area before per-building zonal statistics, so the reads stay in memory. Convert LAS or LAZ points to GeoParquet tables to query them in SQL beside rasters and vectors.

## Related terms

- [Digital elevation model](https://wherobots.com/discover/digital-elevation-model/): the raster most LiDAR surveys are turned into
- [Raster vs vector data](https://wherobots.com/discover/raster-vs-vector-data/): why points and derived grids are handled differently
- [Remote sensing](https://wherobots.com/discover/earth-observation-data/): the discipline LiDAR belongs to as an active sensor
- [Synthetic aperture radar](https://wherobots.com/discover/synthetic-aperture-radar/): the active microwave sensor behind the Copernicus surface model
- [Building footprint](https://wherobots.com/discover/building-footprint/): the polygons LiDAR building heights attach to
- [Coordinate reference system](https://wherobots.com/discover/coordinate-reference-system/): the horizontal and vertical datums every LiDAR product is tied to

## Read more from Wherobots

- [Estimating canopy height with RasterFlow](https://docs.wherobots.com/tutorials/example-notebooks/rasterflow-chm)
- [Raster support in Havasu](https://docs.wherobots.com/reference/havasu/raster/raster-overview)
- [El Niño 2026, atmospheric rivers, and California’s burn scars: one query, two data models](https://wherobots.com/blog/raster-vector-join-high-hazard-basins/)
- [Loading geospatial data with Wherobots](https://docs.wherobots.com/tutorials/example-notebooks/loading-common-spatial-file-types)
- [Raster processing at scale: the out-of-database architecture behind WherobotsDB](https://wherobots.com/blog/raster-processing-at-scale-out-of-database-architecture-wherobotsdb/)

Load LiDAR-derived elevation and canopy rasters into WherobotsDB with a Wherobots free trial at [cloud.wherobots.com](https://cloud.wherobots.com).

## Frequently asked questions

### What is LiDAR data?

LiDAR data is a point cloud: millions of 3D points measured by a laser scanner that times the round trip of each light pulse. Each point has x, y, and z coordinates, an intensity, a return number, and a classification such as ground, vegetation, building, or water. It is the source of most high-resolution terrain, canopy height, and building height maps.

### How is LiDAR data collected?

A scanner on an aircraft, drone, vehicle, tripod, or satellite emits laser pulses. It records the time each reflection takes to return, and the speed of light turns that time into a distance. A satellite positioning (GNSS) receiver records where the scanner was, and an inertial unit records which way it pointed. Together they place each return as a point with map coordinates.

### What is the difference between LiDAR data and a point cloud?

A point cloud is any set of 3D points, and LiDAR data is a point cloud produced by a laser scanner. Photogrammetry also produces point clouds, from overlapping photographs. LiDAR data adds per-point intensity, return number, and multiple returns per pulse, which is how it maps the ground under vegetation.

### What file format is LiDAR data?

LiDAR data is stored in LAS, the binary standard of the American Society for Photogrammetry and Remote Sensing (ASPRS). LAZ is LAS with lossless compression; the LASzip tool writes it at 7 to 25 percent of the LAS size. Cloud Optimized Point Cloud (COPC) is a LAZ 1.4 file with its points grouped into nested cubes, called an octree, so a client can download one area over HTTP. Terrain and canopy grids made from the points are written as GeoTIFF. Points can be converted to GeoParquet tables for SQL analysis.

### How accurate is LiDAR data?

USGS quality levels QL1 and QL2 both require 10 cm vertical accuracy on open ground, measured as the root mean square error of heights (RMSEz). QL1 needs at least 8 pulses per square meter and QL2 at least 2. Accuracy falls under dense canopy and on steep slopes, where fewer pulses reach the ground and ground filtering makes more errors.

### Where can I download free LiDAR data?

Free LiDAR data for the United States is on the USGS 3D Elevation Program through LidarExplorer and The National Map, and on AWS as LAZ tiles and Entwine Point Tiles. NOAA’s Data Access Viewer serves coastal LiDAR, and OpenTopography hosts academic surveys worldwide. The Netherlands (AHN) and England (Environment Agency National LIDAR Programme) publish national LiDAR data as open data.

### Is LiDAR data publicly available?

Yes. Free sources include USGS 3DEP for the United States, NOAA’s coastal surveys, OpenTopography’s research data, and several national programs.

### How can I view LiDAR data?

Open a LAS, LAZ, or COPC file in a point cloud viewer such as CloudCompare, or in a browser viewer that streams COPC. USGS LidarExplorer and OpenTopography preview coverage before download. To view terrain or canopy height, load the derived GeoTIFF DEM or canopy height model in any GIS (geographic information system).

### What is LiDAR in simple terms?

LiDAR measures distance with light. A scanner fires laser pulses many thousands of times a second and times how long each one takes to bounce back. Each measurement becomes a point in 3D, and together the points form a model of the ground, trees, and buildings below.

### What is the difference between a DSM, a DTM, and a canopy height model?

A digital surface model (DSM) is gridded from the first or highest returns and includes trees and roofs. A digital terrain model (DTM) is gridded from ground returns only. A canopy height model is the DSM minus the DTM: the height of vegetation above the ground. The same subtraction inside a building footprint gives building height.

### What are LiDAR classification codes?

Classification codes are ASPRS standard values stored with each LAS point. The common ones are 1 unclassified, 2 ground, 3 to 5 low, medium, and high vegetation, 6 building, 7 low noise, 9 water, 17 bridge deck, and 18 high noise. Values 64 to 255 are free for user definitions.
