[][src]Crate proj5

proj5

PROJ.5 is a Rust-based alternative to the established coordinate projection library PROJ.4 (which is written in C). PROJ.5 aims to make coordinate transformations more type-safe (instead of relying on projection strings) and multi-threaded (using multiple threads as well as generated OpenCL code).

While it is a large undertaking rewriting such a well-established library, the speed benefits from multithreading, vectorization and batched transformation are reason enough to at least try.

I've written this library because I saw various GIS / projection libraries floating around on github, but no centralized Rust-projection library.

Note: This library is a work-in-progress and is by no means battle-tested. It's just a collection of projection formulas from different authors, ported to Rust with a type-safe interface.

Important: Currently, there is no reprojection between ellipsoids yet.

Also important: Coordinates are always horizonal, then vertical. (LonLat instead of LatLon)

PROJ.5 defines the 24 standard ellipsoids (such as WGS84, Bessel, etc.), but you can make your own ellipsoids.

Usage

extern crate proj5;

use proj5::prelude::*;

fn main() {

    //! warning: PROJ.5 can currently not reproject between different ellipsoids!
    //! using different ellipsoids will panic!
    let ellipsoid = WGS_1984_ELLIPSOID;

    let source_coordinates = CoordinateSource::CoordinateBuf(Box::new(
        CoordinateBuf {
            data: vec![(377299.0, 1483035.0)],
            crs: Box::new(UTMSystem {
                utm_zone: 48,
            }),
            ellipsoid: ellipsoid,
        }
    ));

    let mut target_coordinates = CoordinateSource::CoordinateBuf(Box::new(
        CoordinateBuf {
            data: Vec::new(),
            crs: Box::new(MercatorSystem),
            ellipsoid: ellipsoid,
        }
    ));

    let mut strategy = MultithreadingStrategy::SingleCore;
    source_coordinates.project(&mut target_coordinates, &mut strategy);

    println!("first batch of coordinates: {:#?}", target_coordinates.get_data_ref());
}

Performance

Performance is dependent on the chosen MultithreadingStrategy. Of course, a multithreaded transform will always be faster than a single-threaded one. When working with coordinates, X and Y are often calculated seperately, which is why this library does not work with vectors (i.e. libraries such as nalgebra. The transformations are not linear, which is why vectors are in this case useless.

PROJ.5 uses two virtual function calls per (batched) transformation. It is highly, HIGHLY recommended to batch your coordinates, whenever you can. PROJ.5 uses double precision for calculation.

Design

Projecting from any projection and any ellipsoid into any other projection and ellipsoid would result in (number of projections) ^ (number of ellipoids) ^ 2 conversions. This is not realistically possible. Instead, what PROJ.5 does is the following conversion:

This example is not tested
+-----------------+    +------------------+
|(1)              |    |(2)               |
|Source CRS       |    |Longitude / Latit.|
|Source Ellipsoid +-v->+Source Ellipsoid  |
|Source Units     |    |lon/lat (degrees) |
|                 |    |                  |
+-----------------+    +--------+---------+
                                |
                                |
+-----------------+    +--------+---------+
|(4)              |    |(3)               |
|Target CRS       |    |Longitude / Latit.|
|Target Ellipsoid +<-v-+Target Ellipsoid  |
|Target Units     |    |lon/lat (degrees) |
|                 |    |                  |
+-----------------+    +------------------+

The arrows marked with v require a virtual function call, in order to lookup the implementation of the given coordinate system.

In order to implement your own CRS, you have to implement the ToLatLon and FromLatLon traits. The required trait Crs is then automatically implemented for you.

This example is not tested
impl ToLatLon for MyCoordinateSystem {
   fn to_lon_lat(&self, mut data: Vec<(f64, f64)>, ellipsoid: Ellipsoid)
              -> LonLatBuf
   { ... }
}

impl FromLatLon for MyCoordinateSystem {
    fn from_lon_lat(&self, mut data: Vec<(f64, f64)>, ellipsoid: Ellipsoid)
                    -> CoordinateBuf
    { ... }
}

This way, every coordinate system can talk to every other coordinate system.

Modules

crs
prelude
wasm_reexport

Functions that can be called from C or WASM without interacting with Rust types (except for Vec).

Structs

CoordinateBuf

A buffer of coordinates. Units are arbitrary.

Ellipsoid

Ellipsoid struct, to be instantiated with known values

LonLatBuf

A special version of a CoordinateBuf Every CRS that implements the Crs trait can project in and out of a LonLatBuf

Enums

MultithreadingStrategy

How should the coordinate transformation be parallelized?

Constants

AIRY_1830_ELLIPSOID

Airy (1830)

AUSTRALIAN_1966_ELLIPSOID

Australian National (1966)

BESSEL_1841_ELLIPSOID

Bessel (1841)

CLARKE_1866_ELLIPSOID

Clarke (1866)

CLARKE_1878_ELLIPSOID

Clarke (1878)

CLARKE_1880_ELLIPSOID

Clarke (1880)

ELLIPSOIDS

The 24 standard ellipsoids

EVEREST_1830_ELLIPSOID

Everest (1830)

EVEREST_1967_MODIFIED_ELLIPSOID

Everest 1830 Modified (1967)

EVEREST_1967_DEFINITION_ELLIPSOID

Everest 1830 (1967 Definition)

GRS_1967_ELLIPSOID

GRS-67 (1967)

GRS_1980_ELLIPSOID

GRS-80 (1979)

HAYFORD_1910_ELLIPSOID

Hayford (1910)

HELMERT_1906_ELLIPSOID

Helmert (1906)

IERS_1989_ELLIPSOID

IERS (1989)

IERS_2003_ELLIPSOID

IERS (2003)

INTERNATIONAL_1924_ELLIPSOID

International (1924)

KRASSOVSKY_1940_ELLIPSOID

Krassovsky (1940)

MAUPERTUIS_1738_ELLIPSOID

Maupertuis (1738)

NEW_INTERNATIONAL_1967_ELLIPSOID

New International (1967)

PLESSIS_1817_ELLIPSOID

Plessis (1817)

SOUTH_AMERICAN_1969_ELLIPSOID

South American (1969)

WGS_1966_ELLIPSOID

WGS66 (1966)

WGS_1972_ELLIPSOID

WGS-72 (1972)

WGS_1984_ELLIPSOID

WGS-84 (1984)

Traits

Crs
FromLonLat
ToLonLat