pyvista 0.49.2 | vtk 9.7.2 | geopandas 1.2.0 | python-ags4 1.2.0 === Step 1: GEOL intervals with elevations === 1564 intervals in 112 holes | 3,299 m of logged ground | elevations 107.5 to 294.1 m OD intervals holes metres UNIT TOPS 66 66 17.0 MGR 85 36 33.6 HEAD 54 34 33.8 SLIP 320 41 375.9 WHL 11 4 23.8 HMB 21 9 36.6 GOG 7 5 3.1 FE 156 28 302.1 SALS 63 21 145.5 ASLS 25 20 35.0 BLPL 322 34 1026.0 IOG 1 1 2.0 BDS 101 22 354.5 WHM 125 20 418.0 MRB 12 10 11.0 DYS 109 16 164.7 CHAM 20 3 31.4 NR 66 24 285.7 === Step 2: LIDAR terrain === DTM 800 x 800 cells of 5 m, 81.8 to 302.9 m OD === Step 3: build the strata cylinders === 1564 cylinders merged into one mesh: 50,376 points, 40,664 faces === Step 4: render the overview === rendered 01-3d-borehole-logs.png === Step 5: do neighbouring logs agree? The base of the Inferior Oolite === 22 holes log Inferior Oolite limestone resting on Bridport Sand; the contact lies at 190.1 to 234.1 m OD first Bridport Sand material below the contact: {'CLAY': 9, 'MUDSTONE': 9, 'SILT': 3, 'SILTSTONE': 1} 26 pairs of holes within 100 m of each other; 10 agree within 3 m a b metres_apart dz agree_3m DSRC404 DSRC419 6 0.3 True DSRC303 RC509 17 15.2 False DSRC302 RC508 23 13.7 False DSRC406 RC509 29 14.7 False DSRC303 DSRC406 36 0.4 True DSRC303 RC508 38 11.2 False DSRC109 DSRC301 41 0.3 True DSRC406 RC508 44 10.8 False DSRC110 RC509 48 15.2 False RC508 RC509 50 4.0 False DSRC302 DSRC406 56 2.9 True DSRC109 RC507 58 14.2 False DSRC110 DSRC303 59 0.0 True DSRC302 DSRC303 60 2.4 True DSRC302 RC509 70 17.6 False DSRC110 DSRC406 73 0.4 True DSRC325 RC508 73 13.5 False DSRC301 RC507 75 13.9 False DSRC303 DSRC325 80 -2.3 True DSRC325 DSRCOH304 84 1.8 True DSRC302 DSRC325 86 0.2 True DSRC302 RC507 87 9.9 False DSRC319 DSRC325 89 3.5 False DSRC109 DSRCOH304 94 6.3 False DSRC110 RC508 96 11.2 False DSRC325 RC509 97 17.5 False contact minus the median of its neighbours within 100 m (holes with 2+ neighbours): RC509 -15.2 RC507 -13.9 RC508 -11.2 DSRCOH304 -4.0 DSRC406 -0.4 DSRC303 0.2 DSRC325 2.0 DSRC110 5.8 DSRC109 6.3 DSRC302 6.4 DSRC301 6.8 offset by more than 8 m: RC507, RC508, RC509. Without them, 12 pairs agree to within 6.3 m (median 1.1 m) 12 holes reach the contact within 250 m of the close-up centre; their logs record: DSRC110 2.95- 4.00 m Birdlip Limestone Formation slickensides DSRC110 5.30- 6.60 m Birdlip Limestone Formation slickensides RC507 1.60- 8.20 m Birdlip Limestone Formation bedding dipping up to 50 deg RC507 9.70- 11.20 m Birdlip Limestone Formation bedding dipping up to 50 deg RC507 28.36- 37.30 m Birdlip Limestone Formation bedding dipping up to 50 deg RC507 37.30- 45.60 m Bridport Sand Formation bedding dipping up to 50 deg RC509 36.40- 40.20 m Birdlip Limestone Formation slickensides RC509 40.20- 43.20 m Birdlip Limestone Formation slickensides rendered 03-contact-check-3d.png === Step 6: write LineStringZ intervals for QGIS === wrote output/a417_logs_3d.gpkg: 'intervals' 1564 LineStrings with z: True, 'collars' 112 points, 'base_inferior_oolite' 22 points terrain for QGIS 3D: a417_dtm_5m.tif figures written: 01-3d-borehole-logs.png, 02-contact-check-strip-logs.png, 03-contact-check-3d.png