## archived ostn02_phf

A PHF map of the OSTN02 grid shifts for use in transforming ETRS89 grid coordinates to OSGB36

### 14 releases

Uses old Rust 2015

 0.1.13 Jul 24, 2016 Jun 23, 2016 Apr 4, 2016 Mar 16, 2016 Feb 23, 2016

#104 in #geo

Used in lonlat_bng

14MB
372K SLoC

# Description

A Rust Crate which provides fast lookup of OSTN02 adjustments, for the conversion of ETRS89 grid coordinates to OSGB36.

The crate provides base shifts. In order to obtain the actual shifts, divide each shift by `1000.`, then subtract the minimum Easting, Northing, and Height shift. All calculations should be carried out using double-precision floating point.

Minimum Easting shift = `86.275`
Minimum Northing shift = `-81.603`
Minimum height shift = `43.982`

Base shifts for `651, 313`: `(16500, 3359, 270)`
Actual shifts: `(102.775, -78.244, 44.252)`

The FFI function does not require the calculation above; it returns the actual shifts, or (NAN, NAN, NAN)

# Rust Crate Example

``````// The key is the combined hex-transformed (03x) kilometer-grid reference of the ETRS89 Northings and Eastings coordinates
use ostn02_phf::ostn02_lookup;
// Caister Tower Eastings and Northings: 651307.003, 313255.686
let e_grid = (651307.003 / 1000.) as i32;
let n_grid = (313255.686 / 1000.) as i32;
let key = format!("{:03x}{:03x}", n_grid, e_grid);
// key is 13928b
// don't use unwrap() in production
let result = ostn02_lookup(&*key).unwrap();
// result should be (16500, 3359, 270)
assert_eq!(result, (16500, 3359, 270));
// remember that the actual adjustment for a coordinate is a bilinear transform, using a square
// see ostn02_shifts in https://github.com/urschrei/lonlat_bng/blob/master/src/ostn02/mod.rs
``````

# FFI Examples

## Python

``````import sys, ctypes
from ctypes import c_int32, c_double, Structure

class GridRefs(Structure):
_fields_ = [("eastings", c_int32),
("northings", c_int32)]

def __str__(self):
return "({}, {})".format(self.eastings, self.northings)

class Shifts(Structure):
_fields_ = [("x_shift", c_double),
("y_shift", c_double),
("z_shift", c_double)]

def __str__(self):
return "({}, {}, {})".format(self.x_shift, self.y_shift, self.z_shift)

prefix = {'win32': ''}.get(sys.platform, 'lib')
extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
lib = ctypes.cdll.LoadLibrary(prefix + "ostn02_phf" + extension)

lib.get_shifts_ffi.argtypes = (GridRefs,)
lib.get_shifts_ffi.restype = Shifts

result = GridRefs(651, 313)

print(lib.get_shifts_ffi(result))
``````

## C

``````// compile with e.g. `clang -lostn02_phf -L target/release -o ostn02_shifts  src/ostn02.c` from project root
// run with `LD_LIBRARY_PATH=target/release ./ostn02_shifts` from project root
#include <stdio.h>
#include <stdint.h>

typedef struct {
int32_t easting;
int32_t northing;
} gridrefs;

typedef struct {
double x_shift;
double y_shift;
double z_shift;

int main(void) {
gridrefs initial = { .easting = 651, .northing = 313 };
return 0;
}
``````

# Building the Shared Library

• Ensure that Rust is installed
• Clone this repo
• In the repo root, run `cargo build --release`
• The dylib or DLL will be available as `target/release/libostn02_phf.{dylib, dll}`
• If you need to build a `.so` for Linux:
1. `ar -x target/release/liblonlat_bng.a`
2. `gcc -shared *.o -o target/release/libostn02_phf.so`