Skip to content

Commit

Permalink
Comments and much internal change.
Browse files Browse the repository at this point in the history
First "Comment on Rust Geodesy"

Commenting, however, leads to consideration, and
consideration leads to change. So before even
getting going with the commenting, here we go with
a totally reworked version of the communication
between operators and contexts.
  • Loading branch information
busstoptaktik authored Aug 2, 2021
1 parent dd6f10a commit c942d14
Show file tree
Hide file tree
Showing 17 changed files with 574 additions and 163 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Geodesy

*Rust Geodesy* (RG), is a platform for experiments with geodetic software, transformations, and standards. *RG* vaguely resembles the [PROJ](https://proj.org) transformation system, and was built in part on the basis of experiments with alternative data flow models for PROJ. The actual transformation functionality of *RG* is, however, minimal.
*Rust Geodesy* (RG), is a platform for experiments with geodetic software, transformations, and standards. *RG* vaguely resembles the [PROJ](https://proj.org) transformation system, and was built in part on the basis of experiments with alternative data flow models for PROJ. The actual transformation functionality of *RG* is, however, minimal: At time of writing, it includes just 3 low level operations:

Hence, viewing *RG* as *another PROJ*, or *PROJ [RIIR](https://github.com/ansuz/RIIR)*, will lead to bad disappointment. At best, you may catch a weak mirage of a *potential* [shape of jazz to come](https://en.wikipedia.org/wiki/The_Shape_of_Jazz_to_Come) for the PROJ internal dataflow.
1. The three-parameter *Helmert transformation*
2. Helmert's companion, the *cartesian/geographic* coordinate conversion
3. The *transverse mercator* projection

While this is just enough to test the architecture, it is very far from enough to get through a geodesist's daily work.

Hence, viewing *RG* as *another PROJ*, or *PROJ [RiiR](https://acronyms.thefreedictionary.com/RIIR)*, will lead to bad disappointment. At best, you may catch a weak mirage of a *potential* [shape of jazz to come](https://en.wikipedia.org/wiki/The_Shape_of_Jazz_to_Come) for the PROJ internal dataflow.

But dataflow experimentation is just one aspect of *RG*. Overall, the aims are fourfold:

Expand All @@ -15,13 +21,13 @@ All four aims are guided by a wish to amend explicitly identified shortcomings i

## Documentation

The documentation is currently very limited, but take a look at the [examples](examples), and the tests embedded in the source code.
The documentation is currently very limited, but take a look at the [examples](examples), at the tests embedded in the source code, and at this blog style [comment](/comments/000-comment.md), outlining the overall philosophy and architecture of *Rust Geodesy*.

## License

*Rust Geodesy* is Copyright 2020, 2021 by Thomas Knudsen <[email protected]>
*Rust Geodesy*: Copyright 2020, 2021 by Thomas Knudsen <[email protected]>.

it is licensed under either of
Licensed under either of

* Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or [here](http://www.apache.org/licenses/LICENSE-2.0))
Expand Down
327 changes: 327 additions & 0 deletions comments/000-comment.md

Large diffs are not rendered by default.

47 changes: 25 additions & 22 deletions examples/00-transformations.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use geodesy::CoordinateTuple as C;

// examples/00-transformations.rs

// Using Rust Geodesy to transform geodata.
// Run with:
// cargo run --example 00-transformations

fn main() {
// The context is the entry point to all transformation functionality
// The CoordinateTuple type is much used, so
// we give it a very brief abbreviation
use geodesy::CoordinateTuple as C;

// The context is the entry point to all transformation functionality:
let mut ctx = geodesy::Context::new();
// The concept of a "context data structure" will be well known to
// PROJ users, where the context plays a somewhat free-flowing role,
Expand All @@ -17,15 +19,15 @@ fn main() {
// methods of the context data structure.

// We need some coordinates to test the code. The convenience methods
// `gis` an `geo` produces a 4D coordinate tuple and automatically handles
// `gis` and `geo` produces a 4D coordinate tuple and automatically handles
// conversion of the angular parts to radians, and geographical coordinates
// in latitude/longitude order, to the GIS convention of longitude/latitude.
let cph = C::gis(12., 55., 0., 0.); // Copenhagen
let osl = C::gis(10., 60., 0., 0.); // Oslo
let sth = C::geo(59., 18., 0., 0.); // Stockholm
let hel = C::geo(60., 25., 0., 0.); // Helsinki

// `gis` and `geo` has a sibling `raw` which generates coordinate tuples
// `gis` and `geo` have a sibling `raw` which generates coordinate tuples
// from raw numbers, in case your point coordinates are already given in
// radians. But since a coordinate tuple is really just an array of 4
// double precision numbers, you can also generate it directly using plain
Expand All @@ -46,17 +48,9 @@ fn main() {
// this may go wrong (e.g. due to syntax errors in the operator
// definition), use the Rust `match` syntax to handle errors.
let utm32 = match ctx.operator("utm: {zone: 32}") {
Err(e) => return println!("Awful error: {}", e),
Ok(op) => op,
};

// Here's an example of handling bad syntax:
println!("Bad syntax example:");
let _aargh = match ctx.operator("aargh: {zone: 23}") {
Err(e) => (println!(" Deliberate error: {}", e), 0).1,
Ok(op) => op,
Some(op) => op,
None => return println!("{}", ctx.report()),
};

// Now, let's use the utm32-operator to transform some data
ctx.fwd(utm32, &mut data);

Expand All @@ -68,16 +62,22 @@ fn main() {
// The inv() method takes us back to geographic coordinates
ctx.inv(utm32, &mut data);

// The output is in radians, so we use this convenience method:
// The output is in radians, so we use this convenience function:
C::degrees_all(&mut data);

println!("Roundtrip to geo:");
for coord in data {
println!(" {:?}", coord);
}

// To get rid of roundtrip-roundoff, let's make a fresh version
// of the input data for the next example:
// Here's an example of handling bad syntax:
println!("Bad syntax example:");
if ctx.operator("aargh: {zone: 23}").is_none() {
println!("Deliberate error - {}", ctx.report());
}

// To get rid of roundtrip-roundoff noise, let's make a fresh
// version of the input data for the next example:
let mut data = [osl, cph, sth, hel];

// Now a slightly more complex case: Transforming the coordinates,
Expand All @@ -96,15 +96,18 @@ fn main() {
]
}";

let ed50_wgs84 = match ctx.operator(pipeline) {
Err(e) => return println!("Awful error: {}", e),
Ok(op) => op,
let ed50_wgs84 = ctx.operator(pipeline);
if ed50_wgs84.is_none() {
println!("ERROR - {}", ctx.report());
return;
};
let ed50_wgs84 = ed50_wgs84.unwrap();

// Since the forward transformation goes *from* ed50 to wgs84, we use
// the inverse method to take us the other way, back in time to ED50
ctx.inv(ed50_wgs84, &mut data);
// Convert internal lon/lat-in-rad to lat/lon-in-deg.
// Convert the internal lon/lat-in-radians format to the more human
// readable lat/lon-in-degrees - then print
C::geo_all(&mut data);
println!("ed50:");
for coord in data {
Expand Down
30 changes: 15 additions & 15 deletions examples/02-user_defined_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,20 @@ fn main() {

// Now let's see whether it works - instantiate the macro, using the same
// parameters as used in example 00.
let ed50_wgs84 =
match ctx.operator("geohelmert: {left: intl, right: GRS80, dx: -87, dy: -96, dz: -120}") {
Err(e) => return println!("Awful error: {}", e),
Ok(op) => op,
};

// Now do the same transformation as in example 00
ctx.inv(ed50_wgs84, &mut data);

// geo_all(data) transforms all elements in data from the internal GIS
// format (lon/lat in radians) to lat/lon in degrees.
C::geo_all(&mut data);
println!("ed50:");
for coord in data {
println!(" {:?}", coord);
if let Some(ed50_wgs84) =
ctx.operator("geohelmert: {left: intl, right: GRS80, dx: -87, dy: -96, dz: -120}")
{
// Now do the same transformation as in example 00
ctx.inv(ed50_wgs84, &mut data);

// geo_all(data) transforms all elements in data from the internal GIS
// format (lon/lat in radians) to lat/lon in degrees.
C::geo_all(&mut data);
println!("ed50:");
for coord in data {
println!(" {:?}", coord);
}
} else {
println!("{}", ctx.report());
}
}
15 changes: 9 additions & 6 deletions examples/03-user_defined_operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct Add42 {
}

impl Add42 {
fn new(args: &mut OperatorArgs) -> Result<Add42, String> {
fn new(args: &mut OperatorArgs) -> Result<Add42, &'static str> {
let inverted = args.flag("inv");
Ok(Add42 {
args: args.clone(),
Expand All @@ -33,7 +33,7 @@ impl Add42 {

// This is the interface to the Rust Geodesy library: Construct an Add42
// element, and wrap it properly for consumption. It is 100% boilerplate.
pub fn operator(args: &mut OperatorArgs, _ctx: &mut Context) -> Result<Operator, String> {
pub fn operator(args: &mut OperatorArgs, _ctx: &mut Context) -> Result<Operator, &'static str> {
let op = Add42::new(args)?;
Ok(Operator(Box::new(op)))
}
Expand Down Expand Up @@ -72,8 +72,11 @@ fn main() {
ctx.register_operator("add42", Add42::operator);

let add42 = match ctx.operator("add42: {}") {
Err(e) => return println!("Awful error: {}", e),
Ok(op) => op,
Some(value) => value,
None => {
println!("Awful!");
return;
}
};

// Same test coordinates as in example 00, but no conversion to radians.
Expand All @@ -90,14 +93,14 @@ fn main() {

// Now do the transformation
ctx.fwd(add42, &mut data);
println!("add42:");
println!("add42 (fwd):");
for coord in data {
println!(" {:?}", coord);
}

// And go back...
ctx.inv(add42, &mut data);
println!("add42:");
println!("add42 (inv):");
for coord in data {
println!(" {:?}", coord);
}
Expand Down
17 changes: 11 additions & 6 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Justfile for the Rust Geodesy project.

alias t := test
alias c := check
alias r := run
alias t := test

# Defaults to test.
default: test
Expand All @@ -22,6 +23,10 @@ check: test
doc:
cargo doc --no-deps --open

# Run default application.
run:
cargo run

# Run example based on its unique prefix (e.g. 00, 01, etc.).
run-example EXAMPLE:
cargo run --example `basename examples/"{{EXAMPLE}}"* .rs`
Expand All @@ -35,23 +40,23 @@ run-all:
cargo run --example 03-user_defined_operators

# Show diff of all 'git add'-ed files
diff: && status
diff: && stat
git diff

# Given check passes, commit what has been "git add"-ed
commit: check && status
commit: check && stat
git commit

# Given check passes, add everything and commit all changes
commit-all: check && status
commit-all: check && stat
git commit -a

# As commit-all but use MESSAGE as commit-message
commit-fast MESSAGE: check && status
commit-fast MESSAGE: check && stat
git commit -a -m "{{MESSAGE}}"

# Git status
status:
stat:
git status

# Compact format log for changelog report
Expand Down
23 changes: 15 additions & 8 deletions src/bibliography.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub enum Bibliography {

/// B.R. Bowring (1985): *The accuracy of geodetic latitude and height equations*.
/// Survey Review, 28(218), pp.202-206,
/// [DOI](https://doi.org/10.1179/sre.1985.28.218.202)
/// [DOI](https://doi.org/10.1179/sre.1985.28.218.202).
Bow85,

/// B.R. Bowring (1989): *Transverse mercator equations obtained from a spherical basis*.
Expand All @@ -25,6 +25,14 @@ pub enum Bibliography {
/// [DOI](https://doi.org/10.1016/j.cageo.2019.104307)
Cla19,

/// R.E. Deakin, M.N. Hunter and C.F.F. Karney (2012):
/// *A fresh look at the UTM projection:
/// Karney-Krueger equations*.
/// Surveying and Spatial Sciences Institute (SSSI)
/// Land Surveying Commission National Conference,
/// Melbourne, 18-21 April, 2012.
Dea12,

/// Toshio Fukushima (1999): *Fast transform from geocentric to geodetic coordinates*.
/// Journal of Geodesy, 73(11), pp.603–610
/// [DOI](https://doi.org/10.1007/s001900050271)
Expand Down Expand Up @@ -52,13 +60,12 @@ pub enum Bibliography {
/// [DOI](https://doi.org/10.1007/s00190-012-0578-z)
Kar13,

/// R.E. Deakin, M.N. Hunter and C.F.F. Karney (2012):
/// *A fresh look at the UTM projection:
/// Karney-Krueger equations*.
/// Surveying and Spatial Sciences Institute (SSSI)
/// Land Surveying Commission National Conference,
/// Melbourne, 18-21 April, 2012.
Dea12,
/// Thomas Knudsen, Kristian Evers, Geir Arne Hjelle,
/// Guðmundur Valsson, Martin Lidberg and Pasi Häkli (2019):
/// *The Bricks and Mortar for Contemporary Reimplementation
/// of Legacy Nordic Transformations*.
/// Geophysica, 54(1), pp. 107–116.
Knu19,

/// L. Krüger (1912). *Konforme Abbildung des Erdellipsoids in der Ebene*.
/// Royal Prussian Geodetic Institute, New Series 52.
Expand Down
18 changes: 13 additions & 5 deletions src/bin/kp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@
fn main() {
use geodesy::CoordinateTuple as C;
let mut ctx = geodesy::Context::new();
ctx.salat();

if let Some(utm32) = ctx.operator("utm: {zone: 32}") {
let copenhagen = C::geo(55., 12., 0., 0.);
let stockholm = C::geo(59., 18., 0., 0.);
let mut data = [copenhagen, stockholm];

ctx.fwd(utm32, &mut data);
println!("{:?}", data);
}

let coo = C([1., 2., 3., 4.]);
println!("coo: {:?}", coo);
Expand Down Expand Up @@ -43,8 +51,8 @@ fn main() {
}

let utm32 = match ctx.operator("utm: {zone: 32}") {
Err(e) => return println!("Awful error: {}", e),
Ok(op) => op,
None => return println!("Awful error"),
Some(op) => op,
};

ctx.fwd(utm32, &mut data_utm32);
Expand All @@ -62,8 +70,8 @@ fn main() {
}";

let ed50_etrs89 = match ctx.operator(pipeline) {
Err(e) => return println!("Awful error: {}", e),
Ok(op) => op,
None => return println!("Awful error"),
Some(op) => op,
};

ctx.fwd(ed50_etrs89, &mut data_all);
Expand Down
Loading

0 comments on commit c942d14

Please sign in to comment.