QGIS3 plugin to import survex .3d files

  For the QGIS 2 plugin visit
https://github.com/patrickbwarren/qgis-survex-import

  Features

•   no dependencies, natively reads binary v8 format survex .3d files;

•   import stations and legs with full metadata;

•   create passage walls, cross-sections, and polygons from LRUD data;

•   all features have z dimensions, and (mean) elevations to assist coloring;

•   CRS can be set from PROJ.4 string embedded in .3d file;

•   results can be saved immediately into a GeoPackage (.gpkg) shapefile.

  Installation

To install the plugin:

•   clone or download this repository;

•   copy survex_import to python/plugins/ in the current active profile, the location of which can be found from within QGIS3 by going to 'Settings → User Profiles → Open Active Profile Folder' (*);

•   enable the plugin in QGIS3 by going to 'Plugins → Manage and Install Plugins...'; make sure the box next to 'Import .3d file' is checked, in the 'Installed' tab.

(*) Alternatively if you have pb_tool you can run pb_tool deploy from within the survex_import directory.

When installed, a menu item 'Import .3d file' should appear on the 'Vector' drop-down menu in the main QGIS3 window, and (if enabled) a .3d icon in a toolbar.

  Usage

Selecting 'Import .3d file' (or clicking on the .3d icon) brings up a window for the user to select a .3d file with a number of options:

•   Import legs, with options to include splay, duplicate, and surface legs;

•   Import stations, with the option to include surface stations (*);

•   Import passage data computed from LRUDs, with the option to use clino weights (see below):

    •   as polygons, with an option to include mean up / down data;

    •   as walls;

    •   as cross sections;

    •   as traverses, showing the centrelines used for above;

•   Get CRS from .3d file, or inherit from QGIS3 project;

•   Keep features from previous import(s);

•   Select a GeoPackage (.gpkg) file to save results (optional).

(*) In rare cases a station may be flagged both surface and underground, in which case it is imported even if the 'surface' option is left unchecked.

On clicking OK, vector layers are created to contain the imported features as desired. Legs, walls, cross sections, and traverses are imported as line strings in separate vector layers for convenience. All created layers are saved to the GeoPackage file if requested (any existing content is overwritten).

If 'keep features' is selected, then previously imported features are not discarded, and the newly-created layers will contain both the previously imported features plus any new features imported from the designated .3d file. This choice allows processed survey data sets to be combined from multiple sources. Note that cumulative imports do not result in features being overwritten, even if they happen to share the same name, since all features are assigned a unique ID.

  Imported attributes

All layers are created with an ELEVATION attribute, for convenience. For stations this is the just the z dimension. For all other features it is the mean elevation.

For station and leg layers, the following additional attribute fields that are created:

•   stations: NAME, and flags SURFACE, UNDERGROUND, ENTRANCE, EXPORTED, FIXED, ANON

•   legs: NAME, STYLE, DATE1, DATE2, NLEGS (*), LENGTH (*), ERROR (*), ERROR_HORIZ (*), ERROR_VERT (*), and flags SURFACE, DUPLICATE, SPLAY

(*) These fields correspond to the error data reported in the .3d file, which is only generated (by survex) if loop closures are present.

The flags are integer fields set to 0 or 1.

The STYLE field for legs is one of NORMAL, DIVING, CARTESIAN, CYLPOLAR, or NOSURVEY.

The DATE fields are either the same, or represent a date range, in the standard QGIS3 format YYYY-MM-DD.

If up / down data for passage polygons is requested, then the polygons have MEAN_UP and MEAN_DOWN attributes in addition to ELEVATION. These are computed from the LRUD data for the two stations at either end of the leg. They can be used in 3d work (see end).

For the most part importing the CRS from the .3d file should work as expected if the survey data has been georeferenced using the survex *cs and *cs out commands. If it doesn't work, or this information isn't present, one can instead inherit the CRS from the current QGIS3 project. If neither of these options is selected, a CRS dialog box may appear for each layer, or a default CRS will be chosen automatically, depending on the system-wide QGIS3 settings. To maximise the likelihood that CRS import from .3d file works as expected, use an EPSG code in the *cs out survex command rather than a PROJ.4 string.

  Passage walls

Passage walls (as line strings), polygons, and cross sections (as lines) are computed from the left and right measurements in the LRUD data in the same way that the aven viewer in survex displays passage 'tubes' (well, near enough...). The direction of travel (bearing) is worked out, and used to compute the positions of points on the left and right hand passage walls. These wall points are then assembled into the desired features (walls, polygons, cross sections).

The direction of travel is inferred from the directions of the two legs on either side of the given station (with special treatment for stations at the start and end of a traverse). In averaging these, either the legs can be weighted equally (except true plumbs which break the sequence), or the option is given to weight legs by the cosine of the inclination (computed from the processed data, not the actual clino reading). The former is the default, and the latter corresponds to checking the 'use clino weights' box in the import dialog. This alternative option downplays the significance of the occasional steeply inclined leg in an otherwise horizontal passage.

One might want to do this for the following reason. In the 'good old days' steeply inclined legs were usually avoided as they are difficult to sight a compass along, and instead good practice was to keep legs mostly horizontal and add in the occasional plumbed leg when dealing with rough ground. Also pitches were nearly always plumbed. This meant that inferring passage direction as a simple average, ignoring plumbed legs, was most likely correct. For modern surveying with digital instruments, this is no longer the case: there is no loss of accuracy for steeply inclined legs, and shining a laser down a pitch at an off-vertical angle is no problem. Therefore, the 'use clino weights' option has been invented to give such steeply included legs less weight when inferring the passage direction. Note that in a steeply inclined passage, all legs are likely roughly equally inclined, and therefore roughly equally weighted, so using clino weights shouldn't affect the inferred direction of travel in that situation.

TL;DR: if in doubt try first with the 'use clino weights' option selected.

Note that passage wall data is inferred and any resemblence to reality may be pure coincidence: if in doubt, use splays!

  What to do next

Once the data is in QGIS3 one can do various things with it.

For example, features (stations, legs, polygons) can be colored by elevation to mimic the behaviour of the aven viewer in survex (hat tip Julian Todd for figuring some of this out). The easiest way to do this is to use the .qml style files provided in this repository. For example to color legs by depth, open the properties dialog and under the 'Style' tab, at the bottom select 'Style → Load Style', then choose one of the color_lines_by_elevation*.qml style files. This will apply a color scheme to the ELEVATION field data with an inverted spectral color ramp. Use lines for legs, walls, cross sections and traverses; points for stations; and polygons for polygons.

Two versions of these style files are provided.

The first version uses a graduated, inverted spectral color ramp to color ranges of ELEVATION. A small limitation is that these ranges are not automatically updated to match the vertical range of the current data set, but these can be refreshed by clicking on 'Classify' (then 'Apply' to see the changes).

The second version uses a simple marker (line, or fill) with the color set by an expression that maps the ELEVATION to a spectral color ramp. There are no ranges here, but rather these styles rely on zmin and zmax variables being set (see 'Variables' tab under layer → Properties). By matching zmin and zmax between layers with these styles, one can be assured that a common coloring scheme is being applied. A handy way to choose values for zmin and zmax is to open the statistics panel (View → Panels → Statistics Panel) to check out the min and max values in the ELEVATION field.

Color legs by date is possible using an expression like day(age("DATE1",'1970-01-01')) (which gives the number of days between the recorded DATE1 and the given date). Color legs by error is also possible.

Another thing one can do is enable 'map tips', for example to use the NAME field. Then, hovering the mouse near a station (or leg) will show the name as a pop-up label. For this to work:

•   'View → Map Tips' should be checked in the main menu;

•   the map tip has to be set up to use the NAME field ('Properties → Display') in the relevant layer;

•   the layer has to be the currently selected one, though one can set the symbology to 'No symbols' to avoid having to display the features.

With a digital elevation model (DEM raster layer) even more interesting things can be done. For example one can use raster interpolation to find the surface elevation at all the imported stations and save for example to a SURFACE_ELEV field. Then, one can use the field calculator to make a DEPTH field containing the depth below surface, as SURFACE_ELEV minus ELEVATION. Stations can be colored by this, or the information can be added to the 'map tip', etc.

Three dimensional views can be made directly in QGIS3 with 3D Map View though more conveniently with the Qgis2threejs plugin, usually in combination with a DEM. To render features in 3d use the z co-ordinate for points and lines. Passage 'tubes' like those in aven can be approximately rendered using LRUD polygons, with the base set to floor level and the extruded height set to roof level. To do this import the MEAN_UP and MEAN_DOWN fields mentioned above and use the field calculator to make two new floating point (double) fields: FLOOR equal to ELEVATION minus MEAN_DOWN, and HEIGHT equal to MEAN_DOWN plus MEAN_UP. Then render the polygons with the z co-ordinate as the absolute FLOOR, and extruded height as HEIGHT.

Note that there is currently a bug in the Qgis2threejs plugin for QGIS3 that causes a python error when features have data defined properties, such as color by elevation using zmin and zmax variables (second option above). The error looks like

    AttributeError:'QgsSimpleLineSymbolLayer' object has no attribute 'dataDefinedProperty'

(The problem doesn't arise if features are colored by ranges as in the first option above.)

A workaround is as follows. First add zmin and zmax variables into the layer properties (bring up the Properties window and go to the Variables tab): use the green '+' button to add two new variables then click on Apply and OK. Choose values suited to the data set of interest (as above), for example for the DowProv case they can be set to 320 and 400 respectively (elevation in metres ODN). Second, make sure in the main QGIS map window the features in the layer of interest (eg legs) use only a simple style with a fixed colour (this is the default). Third, in the Qgis2threejs Exporter window, double click on the layer of interest (eg legs) to bring up the layer properties, and in the Style panel select Color → Expression. Paste the following into the Expression box.

    ramp_color('Spectral',scale_linear("ELEVATION",@zmin,@zmax,1,0))

If all is well the lines in the Qgis2threejs Exporter preview window should change to be colored by elevation.

Note that if you encountered the python error the plugin may not function correctly any more. It may have to reloaded (which can be done if you have installed the 'Plugin Reloader' plugin); or QGIS3 restarted.

  Example

Sample georeferenced survey data can be found in the example directory as DowProv.3d (example/DowProv.3d).

The corresponding GeoPackage file is in the example directory as DowProv.gpkg (example/DowProv.gpkg).

Further notes on cave surveying and GIS are in cave_surveying_and_GIS.pdf (cave_surveying_and_GIS.pdf) in docs.

  Copying

Code in this repository is licensed under GLP v2:

This program is free software: you can redistribute it and / or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

  Copyright

The .3d file parser is based on a GPL v2 library to handle Survex 3D files (*.3d), copyright © 2008-2012 Thomas Holder, http://sf.net/users/speleo3/; see https://github.com/speleo3/inkscape-speleo.

Modifications and extensions copyright © (2018-2019) Patrick B Warren.