Building Flexible and Powerful Cross-Sections with GridPaper and WebGL

Chris Cooper
Life at Propeller
Published in
6 min readDec 15, 2023

Chris Cooper — Principal Research Engineer @ Propeller

“In the realm of graphs, the chart takes flight,
Contours and slopes, revealing Earth’s might.
Surveyed surfaces, with precision defined,
Unveiling landscapes, nature’s secrets unwind.” — ChatGPT

Cross sections are a powerful way of understanding aspects of the world around us. Concepts that are complex and hard to reason about in three dimensional space can become intuitive when you consider just a two dimensional slice of that space via a cross section.

Alexander von Humboldt, diagram of a cross-section of the earth’s crust, 1841 — link

Propeller’s users can create and view their own cross sections of their worksites, giving them valuable insights. You can compare the current drone survey to previous ones, or to future plans for the site’s shape. You can also see how deep cables, pipes, and other underground utilities are buried or measure clearances to above-ground structures like bridges.

Our previous simple cross sections rendered with an open source SVG charting library.
Interactive cross sections rendered using the GridPaper in-house WebGL rendering engine.

For several years we had simple cross section charts in our platform. The underlying visualisation technology was mixed, with one open source charting library used for interactive charts in the desktop web app, and another for PDF exports. The original authors of the open source libraries intended them more for traditional bar, line and pie charts. Adapting them for use in Propeller worksite cross sections was clumsy, making it hard for our engineers to maintain and extend. It did not spark joy.

Time for a rethink…

As users kept asking for improvements to the cross section chart, we started to wonder if there was a better graphics technology to build on. Something that could be a base for our plans for desktop, mobile app and PDF reports. And we weighed up the pros and cons of another open source third party library vs something built in-house. Ultimately we decided on building something in-house for this task.

An important choice to make early on is what web graphics technology to use. There are three primary Web graphics APIs that we could leverage: Scalable Vector Graphics (SVG), the Canvas 2D API, the WebGL Canvas API (or more specifically WebGL2) or WebGPU (not widely available).

WebGL has a more complicated API requiring users to manage cameras, buffers and shaders. It would however be the most scalable solution allowing rendering of very complex cross sections with very smooth pan/zoom thanks to GPU hardware acceleration of rendering.

What is WebGL?

WebGL, a JavaScript API, revolutionises web graphics by enabling interactive 2D and 3D rendering in your web browser without plugins. Developers wield vertex and fragment shaders to manipulate graphics and utilise buffers for efficient rendering. WebGL’s versatility transcends gaming, encompassing a wide range of applications like data visualisation, scientific simulations, and augmented reality.

Setting goals and exploring possibilities

An In-house WebGL cross section rendering engine might bring unexpected benefits in the future, so we set some goals for improving on the previous tech.

  • An aesthetically pleasing digital equivalent to analog drafting grid paper.
  • A natural experience to interact with on laptop, tablet and mobile.
  • Extensible in-house code that we can leverage for future features.
  • Rendering of high geometric complexity (vs SVG or Canvas APIs).
  • Features to facilitate static rendering to PDFs with white paper background (i.e. supporting light and dark themes).

We also added in some stretch goals to support exploring other applications in the future. These capabilities we built in from the start as we knew they would be increasingly difficult to retrofit.

  • We should support 3D data, even though initial usage will be to visualise data in 2D.
  • We will be able to support multiple simultaneous viewports.

Building a good developer experience

It was going to be a non-trivial project, and we weren’t sure which Propeller codebases would use it. So, we built it as its own monorepo and used storybook.js for quick iteration during development. The monorepo ended up with these package directories, each of which gets published to NPM.

Did we use three.js? No, we did not want to live with another large general purpose third party dependency to keep up to date. Instead we used the much slimmer TWGL.js whose sole purpose is to make using the WebGL API less verbose, with vector and matrix math provided by CesiumJS to provide compatibility with our other code.

Graphics building blocks

Here are some of the elements we built…

To give the look and feel of traditional drafting grid paper we want subtle grid lines. Instead of rendering all these lines as geometry, we can use a WebGL fragment shader to generate the lines on a per-pixel basis. This allows a lot of lines to be rendered at little cost, and we can fade the lines in and out as the user zooms.

Text can be complicated to implement in WebGL. Since we don’t need text as geometry, we use the 2D canvas API to render the text, then pass it to WebGL as a texture. Care must be taken to support sharp rendering on retina displays. This text is used to render dynamic labels.

We want to render lines of any width and with a variety of dash patterns. Due to limitations of WebGL this means building lines geometrically from triangles, and worrying about details such as miter limits so lines can have nice sharp corners at a variety of angles. There’s some great info on drawing lines in WebGL here.

To render points we can use small quad geometry (i.e. squares) with a fragment shader to make them appear circular. Using this approach allows us to render many points at a high frame rate.

We use pointer events to allow the user’s mouse or touch to pan and zoom the view. We also support hover highlighting and selection by re-rendering geometry to an offscreen pick buffer. This allows us to render with increased width just in the pick buffer to make selection easier, particularly on touch devices where it is hard to accurately tap on a thin line with your finger..

A cross section cursor brings together various GridPaper primitives. We can set up contrived scenarios in storybook to test the cursor in various ways.

The rendering can also support a light theme for the mobile app and PDF reports..

The viewer code supports multiple simultaneous views of 3D data to allow us to explore future applications of GridPaper.

Where’s it at now?

The GridPaper rendering engine has now been rolled out to production on Propeller for interactive viewing across both desktop and mobile. We now also use it across our PDF reports exported from the platform, to give them a consistent look and feel to the interactive viewers. Ultimately, the development of the GridPaper rendering engine has allowed us to build a much more powerful and responsive interactive cross section cursor in addition to opening up future opportunities of workflows requiring simultaneous 3D data views.

GridPaper cross sections in the Propeller mobile app

--

--