Coastal Survey Automation
A tool that turns raw hydrographic survey data into the as-built control sheets used to check that each coastal groyne is built to its design.
Sole developer. Design and build of the whole toolchain: survey-format parsers, the linear reference-system engine, the six-stage processing pipeline, and the Excel/VBA sheet generator.
the contractor is building a line of groynes along the this stretch of the West African coast to slow coastal erosion. Each groyne is placed layer by layer, from the excavation and bedding up to the graded rock armour and the roundhead, and every layer has to be surveyed and compared against its theoretical design. This tool takes the survey exports (tracks, surfaces, point sets, dredger logs) out of the survey software, rebuilds the design profiles, computes each point's position along the groyne axis, and produces both the theoretical data and the as-built data for the control sheet. An Excel macro then assembles that data into the formatted inspection sheet the survey team hands over. It removes a slow, manual copy step between the survey software and Excel that had to be redone at every survey.
The problem
For every groyne and every construction layer, the survey team had to compare the theoretical design profile to the actual survey, section by section along the structure. Getting the theoretical points and the as-built points into the control sheet meant reading them out of the survey software and reshaping them by hand in Excel, layer after layer, groyne after groyne. It was slow, it had to be redone at every new survey, and a single mis-keyed coordinate changes the verdict on whether the structure is within tolerance.
The approach
The toolchain is a single Python codebase with no third-party libraries: the geometry, the coordinate transforms and the file parsers are all written from scratch. It reads and writes the survey software's native formats directly (tracks, triangulated surfaces, point sets, line sets, dredger logs), and shells out to the software's own profile-cutting command where that is faster and safer than reimplementing surface interpolation. Around it, all the project-specific rules (rock grades, which layers borrow endpoints from which, matching tolerances) sit in configuration modules, and a small Excel/VBA macro does the last step, pulling the generated CSVs into the formatted sheet on a single button press.
The result
- The manual copy step between the survey software and Excel is gone: an operator picks a groyne, runs the pipeline, and the control sheet is filled from one button in Excel.
- The theoretical profile for a groyne is rebuilt the same way every time, so two surveyors checking the same structure work from identical reference data.
- Re-running a survey is cheap: the same command regenerates everything instead of a fresh round of manual entry.
Concrete usage figures for this project are not published.
Key features
- Reads the survey software's own file formats directly: tracks, triangulated surfaces, point sets, line sets and dredger logs
- One command per groyne rebuilds the full set of design profiles, layer by layer, roundhead included
- Places every survey point along the groyne axis (distance along the axis, offset from the centreline), the way the control sheet reads
- Matches the dredger and survey logs against the design points automatically, and assigns each point to the right groyne and layer
- Fills gaps in the survey: where the centreline point is missing, it interpolates depth from the nearest points on each side
- Merges every groyne's surfaces into one progress surface per layer for the whole project
- Excel macro that builds the formatted control sheet for a groyne on a single button press
- All project rules (rock grades, layer relationships, tolerances) live in configuration, not buried in code
Engineering — Architecture, decisions and trade-offs
Architecture
Single Python 3 codebase, around 9,400 lines, with no third-party runtime dependencies. Geometry and coordinate maths are hand-written on immutable dataclasses (Point2D/3D, Vector2D, ReferenceLine, KP/Offset). The core is a CoordinateSystem class that converts Easting/Northing into a linear reference system along each groyne's centreline (projection onto a normalised axis vector and its perpendicular) and back, replacing an earlier set of loose functions that are kept as deprecated wrappers. I/O is one reader and one writer per survey format (TRK, TRS, PTS, LIS, LOG, CSV, PLI) under an io/ package. The six processing stages live in generators/ (sharing a Generator base that resolves the project's directory layout) and in self-contained use_case/ modules, each with its own cli, config and main. run.py is a use-case registry: adding a stage is about five lines and the interactive menu and help text are generated from it. Everything project-specific (the nine rock-grade layers, the cross-layer endpoint-borrowing config with per-relation excluded KPs, centreline-removal rules, all matching tolerances) is in config/ modules. Paths switch on the OS (mapped Z: drive on Windows, POSIX path on Linux). A custom logging layer writes a timestamped run log per use case. The last stage is an Excel workbook driven by around 1,300 lines of VBA that imports the generated CSVs, builds one worksheet per layer with point IDs, section separators and a control block, and drops in a plan-view image.
Engineering challenges
- Linear reference system per groyne: each structure has its own centreline (read from a line-set file, with a hard-coded fallback), and every point needs its distance along the axis and its signed offset. This is done with a normalised axis vector and its perpendicular, with a round-trip check (E/N to KP/offset and back) to catch a bad reference line before it corrupts a whole sheet.
- Missing centreline points: the cut profiles do not always carry a point exactly on the axis at the sections the sheet expects. Where a point is missing and there is survey data on both sides, the tool creates one, with depth interpolated by distance between the nearest left and right points; where one side is missing, it leaves the gap rather than guess.
- Assigning log points to a groyne and a layer: dredger logs are a flat stream of coordinates. Each point is transformed into the linear system, tested against the design points within KP, offset and depth tolerances, and routed to the groyne and layer it belongs to.
- Ordering points geographically for the sheet: main-axis points are sorted by KP then offset, and the roundhead point sets are appended in a configured left-to-centre-to-right order, so the sheet reads along the structure the way an inspector walks it.
Technical decisions
- No third-party libraries: the geometry is simple and the deploy target is a locked-down survey workstation on a mapped drive. Hand-writing the vector maths and the parsers kept the tool a single copyable folder with nothing to install.
- Reuse the survey software's own profile-cutting command (
gentrk) instead of reimplementing surface interpolation: it is the reference behaviour the team already trusts, and shelling out to it was faster and lower-risk than rebuilding it. - All domain rules in configuration, not code: rock grades, cross-layer endpoint borrowing, excluded KPs and tolerances change per project and per survey campaign. Keeping them in
config/modules makes a rule change a data edit. - Excel/VBA for the last mile: the deliverable is a formatted sheet the survey team already works in. Generating the data as CSV and letting a macro assemble the workbook kept the output in their tool instead of forcing a new one.
- Use-case registry in
run.py: the pipeline grew stage by stage (logs, merge, profiles, point sets, CSV, PLI). A registry made each stage a self-contained module and the menu self-generating.
Stack
- Python 3
- dataclasses
- VBA (Excel macros)
- DredgeView survey formats (TRK / TRS / PTS / LIS / LOG / PLI)
- gentrk CLI
- CSV
- Git
Sole developer. Design and build of the whole toolchain: survey-format parsers, the linear reference-system engine, the six-stage processing pipeline, and the Excel/VBA sheet generator. — A Dutch dredging and marine-contracting multinational — in-house tool for a coastal-protection project on the West African coast. (2025)