mfbonfigli / gocesiumtiler

A Cesium.js point cloud 3D tiles generator from LAS files written in Golang
Mozilla Public License 2.0
195 stars 40 forks source link

Feat/proj upgrade #56

Closed mfbonfigli closed 1 week ago

mfbonfigli commented 2 weeks ago

What

This big CR adds three changes:

  1. Support for PROJ 9.x+, including a brand new way of building the system using Dockerfiles
  2. Slightly improves performances by using array-backed linked lists that are more cpu friendly on the cache
  3. The license has been changed from LGPL to Mozilla Public License 2.0

Why

The current version of gocesiumtiler uses a built in version of Proj 4.9.2. While this version works, it is a decade old, cannot be updated / upgraded, brings some concerns in terms of thread safety and severely lags behind the modern versions of Proj in terms of supported projections.

Unfortunately, there are no go native libraries to perform coordinate conversion, hence the upgrade of Proj remains the only reasonable path forward to removing the dependency on Proj 4.9.2.

How

The upgrade from Proj4 to the newer Proj versions was not trivial. Proj4 was a self-contained, zero dependencies, C library, whereas the newer versions are C/C++ libraries with external dependencies, namely SQLite, Libtiff and CURL.

One of the main objectives of gocesiumtiler is to remain as much self contained as possible to maximize ease of use and portability. This means that the go code should be statically linked at build time with the Proj library and its dependencies, resulting in a single portable executable.

In order to achieve that, Proj had to be rebuilt statically from the sources for both the Windows and Linux x86-64 environments, which adds significant complexity to the project development setup.

In order to achieve reproducible builds, a Dockerfile has been added. This leverages multi-stage builds, mingw64 and vcpkg to cross build, under a linux environment, for both linux and windows.

For local development, a DEVELOPMENT.md file has been included which explains how to setup the dev environment in Windows, outside of Docker.

Backward incompatible changes

The CR introduces a few backward incompatible changes:

  1. The -geoid flag in the CLI has been removed, and the geoid to ellipsoid utilities removed.

The reason for this change is that the code used for coordinate conversion was under LGPL, forcing this library also to be released under those terms. LGPL however doesn't fit well a go-based environment because the code in go statically builds with other code bases. The Mozilla Public License 2.0 instead is more appropriate as it limits the scope to the source files, encouraging contributions back to the project but not limiting commercial usage of the library embedded in other products. At this moment the even more permissive MIT license is not being considered, but could be in future.

Having said this, the vertical coordinate conversion now it's absorbed by the newer Proj library, which is capable of such conversions. The README.md has been updated to reflecct this.

  1. The --epsg flag (and relative tiler parameter) is now a string and not just an integer. This change allows users to specify combined CRS via supported Proj syntax like "EPSG:32633+3855" or via a Proj4 string or WKT text, giving much more flexibility to the too. The CLI is however still backward compatible as every number X will be considered equivalent to the string "EPSG:X"

Architectural changes

The major change is the introduction of a coordinate conversion factory function type. This is due to the fact that Proj Context instances cannot be shared across threads, hence different goroutines now need to have a way to initialize their own context.

Alternatively, mutex locking could have been used but this would have lead to severely degraded performances.

Development flow changes

The development flow is also changed. If before a simple go build command was sufficient, now first the developer has to compile statically the Proj library.

The DEVELOPMENT.md file has been added to clarify how to setup the development environment.

Additionally two build script, for linux and windows, have been added build.sh and build.ps1. These can be invoked and will use Docker to ensure reproducible builds without installing any dependency on the local system.

Limitations