@@ -406,6 +406,77 @@ USE-CASE : Take a LiDAR map, create a mesh from the ground points, split into ti
406406 buffer.close()
407407
408408
409+ Digital Terrain Model (DTM) Creation Example
410+ ................................................................................
411+
412+ The following is a script sample that can be used to create a DTM from a PDAL-
413+ readable pointcloud.
414+
415+ Method:
416+
417+ #. read point cloud file
418+ #. remove noise
419+ #. clean up invalid values
420+ #. classify ground points using `SMRF <https://pdal.io/en/2.9.2/stages/filters.smrf.html >`__
421+ #. write with `GDAL writer <https://pdal.io/en/2.9.2/stages/writers.gdal.html >`__
422+
423+ .. note :: If your pointcloud already has ground classified, you can skip all but
424+ the reader and writer and achieve the same result.
425+
426+ .. code-block :: python
427+
428+ import pdal
429+
430+ pc_path = ' https://github.com/PDAL/data/raw/refs/heads/main/autzen/autzen.laz'
431+ out_file = ' autzen_dtm.tif'
432+
433+
434+ # read
435+ reader = pdal.Reader.las(pc_path)
436+
437+ # remove noisy points
438+ lownoise_filter = pdal.Filter.range(
439+ limits = ' Classification![7:7]' , tag = ' lownoise'
440+ )
441+ highnoise_filter = pdal.Filter.range(
442+ limits = ' Classification![18:]' , tag = ' highnoise'
443+ )
444+
445+ # saving incorrectly labeled returns here, some people want this, some don't
446+ prepare_ground = pdal.Filter.assign(
447+ value = [
448+ ' Classification=0' ,
449+ ' ReturnNumber=1 WHERE ReturnNumber < 1' ,
450+ ' NumberOfReturns=1 WHERE NumberOfReturns < 1' ,
451+ ],
452+ tag = ' prepare_ground_classifier' ,
453+ )
454+
455+ # classify ground
456+ smrf_classifier = pdal.Filter.smrf(tag = ' ground_classifier' )
457+
458+ # write with gdal, resolution in feet for autzen
459+ gdal_writer = pdal.Writer.gdal(
460+ filename = out_file,
461+ where = ' Classification == 2' ,
462+ data_type = ' float32' ,
463+ resolution = 10 ,
464+ output_type = ' idw' ,
465+ window_size = 3 ,
466+ pdal_metadata = True ,
467+ )
468+
469+ # collect pdal stages and execute pipline
470+ pipeline = (
471+ reader
472+ | lownoise_filter
473+ | highnoise_filter
474+ | prepare_ground
475+ | smrf_classifier
476+ | gdal_writer
477+ )
478+ pipeline.execute()
479+
409480
410481 .. _`Numpy` : http://www.numpy.org/
411482.. _`schema` : http://www.pdal.io/dimensions.html
0 commit comments