Crates.io | proj |
lib.rs | proj |
version | 0.27.2 |
source | src |
created_at | 2015-07-01 03:33:00.125666 |
updated_at | 2023-07-07 10:37:30.817823 |
description | High-level Rust bindings for the latest stable version of PROJ |
homepage | |
repository | https://github.com/georust/proj |
max_upload_size | |
id | 2510 |
size | 133,631 |
Coordinate transformation via bindings to the PROJ v9.2 API.
Two coordinate transformation operations are currently provided: projection (and inverse projection) and conversion.
Projection is intended for transformations between geodetic and projected coordinates and vice versa (inverse projection), while conversion is intended for transformations between projected coordinate systems. The PROJ documentation explains the distinction between these operations in more detail.
This crate depends on libproj v9.2.x
, accessed via the
proj-sys
crate. By default, proj-sys
will try to find a
pre-existing installation of libproj on your system. If an appropriate version of libproj
cannot be found, the build script will attempt to build libproj from source. You may specify a
from-source build with the bundled_proj
feature.
Out of the box, any (x, y)
numeric tuple can be provided as input to proj. You can conform
your own types to the Coord trait to pass
them in directly and avoid intermediate allocations. There is a geo-types
feature, enabled by default, which implements this trait for types in
the geo-types
crate.
Methods for conversion and
projection of slices of Coord
s are also available.
use proj::Proj;
let from = "EPSG:2230";
let to = "EPSG:26946";
let ft_to_m = Proj::new_known_crs(&from, &to, None).unwrap();
let result = ft_to_m
.convert((4760096.421921f64, 3744293.729449f64))
.unwrap();
assert_relative_eq!(result.0, 1450880.2910605003);
assert_relative_eq!(result.1, 1141263.0111604529);
pipeline
OperatorNote that as of v5.0.0, PROJ uses the pipeline
operator, which allows an arbitrary number of steps in a conversion. The example below works as
follows:
define the operation as a pipeline
operation
define step
1 as an inv
erse transform, yielding geodetic coordinates
define step
2 as a forward transform to projected coordinates, yielding metres.
use proj::Proj;
let ft_to_m = Proj::new("
+proj=pipeline
+step +inv +proj=lcc +lat_1=33.88333333333333
+lat_2=32.78333333333333 +lat_0=32.16666666666666
+lon_0=-116.25 +x_0=2000000.0001016 +y_0=500000.0001016001 +ellps=GRS80
+towgs84=0,0,0,0,0,0,0 +units=us-ft +no_defs
+step +proj=lcc +lat_1=33.88333333333333 +lat_2=32.78333333333333 +lat_0=32.16666666666666
+lon_0=-116.25 +x_0=2000000 +y_0=500000
+ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
").unwrap();
// The Presidio, approximately
let result = ft_to_m.convert((4760096.421921f64, 3744293.729449f64)).unwrap();
assert_relative_eq!(result.0, 1450880.2910605003);
assert_relative_eq!(result.1, 1141263.01116045);
use proj::Proj;
// Carry out an inverse projection from Pulkovo 1942(58) / Stereo70 (EPSG 3844)
// into geodetic lon and lat coordinates (in radians)
let stereo70 = Proj::new("
+proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 +y_0=500000
+ellps=krass +towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84
+units=m +no_defs
").unwrap();
let geodetic_radians_point = stereo70.project(
(500119.70352012233f64, 500027.77896348457f64), true
).unwrap();
assert_relative_eq!(geodetic_radians_point.0, 0.436332, epsilon=1e-5);
assert_relative_eq!(geodetic_radians_point.1, 0.802851, epsiolon=1e-5);
There are two options for creating a transformation:
Proj::new
or Proj::new_known_crs
. This creates a transformation instance (Proj
)ProjBuilder
by calling
ProjBuilder::new()
. It may be modified to enable network downloads, disable the grid,
cache or modify search paths;ProjBuilder.proj()
or
ProjBuilder.proj_known_crs()
. This
creates a transformation instance (Proj
)Note:
ProjBuilder
and Proj
implement the Info
trait, which can
be used to get information about the current state of the PROJ
instance;Proj::new()
and ProjBuilder::proj()
have the same signature;Proj::new_known_crs()
and ProjBuilder::proj_known_crs()
have the same signature.By default, the crate requires libproj
9.2.x to be present on your system. While it may be
backwards-compatible with older PROJ 6 versions, this is neither tested nor supported. If a suitable library can't be found, proj
will attempt to build libproj
from source.
geo-types
: include trait impls for
geo-types
. See
example.pkg_config
: enables the use of pkg-config
when linking against libproj
—
note that pkg-config
must be available on your system.bundled_proj
: builds libproj
from source bundled in the proj-sys
crate.
Note that this feature requires Sqlite3 and libtiff
to be present on your
system.network
: exposes APIs which, when enabled, can fetch grid data from the internet to improve
projection accuracy. See enable_network
for details.proj
supports network grid download functionality via
the network
feature. Network access is disabled by default, and can be
activated by passing a true
bool
to
enable_network()
. Network
functionality status can be queried with network_enabled
, and the download endpoint can be
queried and set using get_url_endpoint
and set_url_endpoint
.
Up to 300 mb of downloaded grids are cached to save bandwidth: This cache can be enabled or
disabled using grid_cache_enable
.
The path used to search for resource files can be modified using
set_search_paths
If you have your own geometric types, you can conform them to the Coord
trait and use proj
without any intermediate allocation.
use proj::{Proj, Coord};
struct MyPointOfInterest {
lat: f64,
lon: f64,
}
impl Coord<f64> for MyPointOfInterest {
fn x(&self) -> f64 {
self.lon
}
fn y(&self) -> f64 {
self.lat
}
fn from_xy(x: f64, y: f64) -> Self {
Self { lon: x, lat: y }
}
}
let donut_shop = MyPointOfInterest { lat: 34.095620, lon: -118.283555 };
let from = "EPSG:4326";
let to = "EPSG:3309";
let proj = Proj::new_known_crs(&from, &to, None).unwrap();
let result = proj.convert(donut_shop).unwrap();
assert_relative_eq!(result.x(), 158458.67251293268);
assert_relative_eq!(result.y(), -434296.8803996085);
geo-types
If you've enabled the geo-types
feature, you can skip allocating an intermediate representation,
and pass the geo-types
directly.
use approx::assert_relative_eq;
use proj::Proj;
use geo_types::Point;
let my_point = Point::new(4760096.421921f64, 3744293.729449f64);
let from = "EPSG:2230";
let to = "EPSG:26946";
let nad_ft_to_m = Proj::new_known_crs(&from, &to, None).unwrap();
let result = nad_ft_to_m.convert(my_point).unwrap();
assert_relative_eq!(result.x(), 1450880.2910605003f64);
assert_relative_eq!(result.y(), 1141263.0111604529f64);
You can also transform entire geometries from geo-types
by using the
Transform
trait.
use proj::{Proj, Transform};
use geo_types::{Coordinate, line_string};
let line = line_string![
(x: -116.590457069172_f64, y: 32.55730630167689),
(x: -116.590411068973, y: 32.55714830169309),
];
let proj = Proj::new_known_crs("EPSG:4326", "EPSG:6366", None).unwrap();
// create a new line with a different projection
let new_line = line.transformed(&proj).unwrap();
assert_eq!(new_line[0], Coordinate { x: 538447.8454476658, y: 3602285.563945497, });
assert_eq!(new_line[1], Coordinate { x: 538452.2313532799, y: 3602268.065714932, });
// or transform the original in-place
let mut line = line;
line.transform(&proj).unwrap();
assert_eq!(line[0], Coordinate { x: 538447.8454476658, y: 3602285.563945497, });
assert_eq!(line[1], Coordinate { x: 538452.2313532799, y: 3602268.065714932, });
License: MIT/Apache-2.0