{"id":13496639,"url":"https://github.com/georust/proj","last_synced_at":"2025-05-15T04:05:08.040Z","repository":{"id":34416142,"uuid":"38347679","full_name":"georust/proj","owner":"georust","description":"Rust bindings for the latest stable release of PROJ","archived":false,"fork":false,"pushed_at":"2025-05-09T19:27:26.000Z","size":59737,"stargazers_count":154,"open_issues_count":29,"forks_count":51,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-05-13T02:33:58.239Z","etag":null,"topics":["geocoding","geodesy","geospatial","gis","proj","rust"],"latest_commit_sha":null,"homepage":"https://docs.rs/proj","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/georust.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-07-01T03:32:26.000Z","updated_at":"2025-05-09T19:27:28.000Z","dependencies_parsed_at":"2023-12-16T06:03:01.940Z","dependency_job_id":"2cd54784-886f-4495-9d1c-6d97339d5a38","html_url":"https://github.com/georust/proj","commit_stats":{"total_commits":487,"total_committers":18,"mean_commits":"27.055555555555557","dds":"0.32443531827515404","last_synced_commit":"89f9d54fa3311d1226a59f069a0589355f07a839"},"previous_names":["georust/rust-proj"],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georust%2Fproj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georust%2Fproj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georust%2Fproj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georust%2Fproj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/georust","download_url":"https://codeload.github.com/georust/proj/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270643,"owners_count":22042859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geocoding","geodesy","geospatial","gis","proj","rust"],"created_at":"2024-07-31T19:01:53.926Z","updated_at":"2025-05-15T04:05:03.025Z","avatar_url":"https://github.com/georust.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/georust/proj/test.yml?branch=main)\n# PROJ\n\nCoordinate transformation via bindings to the [PROJ](https://proj.org) v9.4 API.\n\nTwo coordinate transformation operations are currently provided: _projection_ (and inverse\nprojection) and _conversion_.\n\n_Projection_ is intended for transformations between geodetic and projected coordinates and\nvice versa (inverse projection), while _conversion_ is intended for transformations between\nprojected coordinate systems. The PROJ [documentation](https://proj.org/operations/index.html)\nexplains the distinction between these operations in more detail.\n\nThis crate depends on [`libproj v9.4.x`](https://proj.org), accessed via the\n[`proj-sys`](https://docs.rs/proj-sys) crate. By default, `proj-sys` will try to find a\npre-existing installation of libproj on your system. If an appropriate version of libproj\ncannot be found, the build script will attempt to build libproj from source. You may specify a\nfrom-source build with the [`bundled_proj` feature](#feature-flags).\n\nOut of the box, any `(x, y)` numeric tuple can be provided as input to proj. You can [conform\nyour own types](#conform-your-own-types) to the [Coord](https://docs.rs/proj/latest/proj/trait.Coord.html) trait to pass\nthem in directly and avoid intermediate allocations. There is a [`geo-types`\nfeature](#feature-flags), enabled by default, which implements this trait for types in\nthe [`geo-types` crate](https://docs.rs/geo-types).\n\nMethods for [conversion](https://docs.rs/proj/latest/proj/struct.Proj.html#method.convert_array) and\n[projection](https://docs.rs/proj/latest/proj/struct.Proj.html#method.project_array) of slices of `Coord`s are also available.\n\n## Examples\n\n### Convert from [NAD 83 US Survey Feet](https://epsg.io/2230) to [NAD 83 Meters](https://epsg.io/26946) Using EPSG Codes\n\n```rust\nuse proj::Proj;\n\nlet from = \"EPSG:2230\";\nlet to = \"EPSG:26946\";\nlet ft_to_m = Proj::new_known_crs(\u0026from, \u0026to, None).unwrap();\nlet result = ft_to_m\n    .convert((4760096.421921f64, 3744293.729449f64))\n    .unwrap();\nassert_relative_eq!(result.0, 1450880.2910605003);\nassert_relative_eq!(result.1, 1141263.0111604529);\n```\n\n### Convert from [NAD 83 US Survey Feet](https://epsg.io/2230) to [NAD 83 Meters](https://epsg.io/26946) Using the `pipeline` Operator\n\nNote that as of v5.0.0, PROJ uses the [`pipeline`](https://proj.org/operations/pipeline.html)\noperator, which allows an arbitrary number of steps in a conversion. The example below works as\nfollows:\n\n- define the operation as a `pipeline` operation\n- define `step` 1 as an `inv`erse transform, yielding geodetic coordinates\n- define `step` 2 as a forward transform to projected coordinates, yielding metres.\n\n\n```rust\nuse proj::Proj;\n\nlet ft_to_m = Proj::new(\"\n    +proj=pipeline\n    +step +inv +proj=lcc +lat_1=33.88333333333333\n    +lat_2=32.78333333333333 +lat_0=32.16666666666666\n    +lon_0=-116.25 +x_0=2000000.0001016 +y_0=500000.0001016001 +ellps=GRS80\n    +towgs84=0,0,0,0,0,0,0 +units=us-ft +no_defs\n    +step +proj=lcc +lat_1=33.88333333333333 +lat_2=32.78333333333333 +lat_0=32.16666666666666\n    +lon_0=-116.25 +x_0=2000000 +y_0=500000\n    +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\n\").unwrap();\n\n// The Presidio, approximately\nlet result = ft_to_m.convert((4760096.421921f64, 3744293.729449f64)).unwrap();\nassert_relative_eq!(result.0, 1450880.2910605003);\nassert_relative_eq!(result.1, 1141263.01116045);\n```\n\n### Inverse Projection from [Stereo70](https://epsg.io/3844) to Geodetic\n\n```rust\nuse proj::Proj;\n\n// Carry out an inverse projection from Pulkovo 1942(58) / Stereo70 (EPSG 3844)\n// into geodetic lon and lat coordinates (in radians)\nlet stereo70 = Proj::new(\"\n    +proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 +y_0=500000\n    +ellps=krass +towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84\n    +units=m +no_defs\n    \").unwrap();\nlet geodetic_radians_point = stereo70.project(\n    (500119.70352012233f64, 500027.77896348457f64), true\n).unwrap();\nassert_relative_eq!(geodetic_radians_point.0, 0.436332, epsilon=1e-5);\nassert_relative_eq!(geodetic_radians_point.1, 0.802851, epsiolon=1e-5);\n```\n\n## Usage\n\nThere are two options for creating a transformation:\n\n1. If you don't require additional [grids](#grid-file-download) or other customisation:\n    - Call `Proj::new` or `Proj::new_known_crs`. This creates a transformation instance ([`Proj`](https://docs.rs/proj/latest/proj/struct.Proj.html))\n2. If you require a grid for the transformation you wish to carry out, or you need to customise\n   the search path or the grid endpoint:\n   - Create a new [`ProjBuilder`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html) by calling\n     `ProjBuilder::new()`. It may be modified to enable network downloads, disable the grid,\n     cache or modify search paths;\n   - Call [`ProjBuilder.proj()`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html#method.proj) or\n     [`ProjBuilder.proj_known_crs()`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html#method.proj_known_crs). This\n     creates a transformation instance (`Proj`)\n\n**Note**:\n\n1. Both `ProjBuilder` and `Proj` implement the [`Info`](https://docs.rs/proj/latest/proj/trait.Info.html) trait, which can\n   be used to get information about the current state of the `PROJ` instance;\n2. `Proj::new()` and `ProjBuilder::proj()` have the same signature;\n3. `Proj::new_known_crs()` and `ProjBuilder::proj_known_crs()` have the same signature.\n\n## Requirements\n\nBy default, the crate requires `libproj` 9.2.x to be present on your system. While it may be\nbackwards-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.\n\n## Feature Flags\n\n- `geo-types`: include [trait impls for\n  `geo-types`](https://docs.rs/proj/latest/proj/trait.Coord.html#impl-Coord%3CT%3E-for-Coordinate%3CT%3E). See\n  [example](#integration-with-geo-types).\n- `pkg_config`: enables the use of `pkg-config` when linking against `libproj` —\n  note that `pkg-config` must be available on your system.\n- `bundled_proj`: builds `libproj` from source bundled in the `proj-sys` crate.\n  Note that this feature requires Sqlite3 and `libtiff` to be present on your\n  system.\n- `network`: exposes APIs which, when enabled, can fetch grid data from the internet to improve\n  projection accuracy. See [`enable_network`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html#method.enable_network)\n  for details.\n\n### Network, Cache, and Search Path Functionality\n\n#### Grid File Download\n\n`proj` supports [network grid download](https://proj.org/usage/network.html) functionality via\nthe [`network` feature](#feature-flags).  Network access is **disabled** by default, and can be\nactivated by passing a `true` `bool` to\n[`enable_network()`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html#method.enable_network).  Network\nfunctionality status can be queried with `network_enabled`, and the download endpoint can be\nqueried and set using `get_url_endpoint` and `set_url_endpoint`.\n\n##### Grid File Cache\nUp to 300 mb of downloaded grids are cached to save bandwidth: This cache can be enabled or\ndisabled using [`grid_cache_enable`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html#method.grid_cache_enable).\n\n#### Search Path Modification\nThe path used to search for resource files can be modified using\n[`set_search_paths`](https://docs.rs/proj/latest/proj/struct.ProjBuilder.html#method.set_search_paths)\n\n### Conform your own types\n\nIf you have your own geometric types, you can conform them to the `Coord` trait and use `proj`\nwithout any intermediate allocation.\n\n```rust\nuse proj::{Proj, Coord};\n\nstruct MyPointOfInterest {\n    lat: f64,\n    lon: f64,\n}\n\nimpl Coord\u003cf64\u003e for MyPointOfInterest {\n    fn x(\u0026self) -\u003e f64 {\n        self.lon\n    }\n    fn y(\u0026self) -\u003e f64 {\n        self.lat\n    }\n    fn from_xy(x: f64, y: f64) -\u003e Self {\n        Self { lon: x, lat: y }\n    }\n}\n\nlet donut_shop = MyPointOfInterest { lat: 34.095620, lon: -118.283555 };\n\nlet from = \"EPSG:4326\";\nlet to = \"EPSG:3309\";\nlet proj = Proj::new_known_crs(\u0026from, \u0026to, None).unwrap();\n\nlet result = proj.convert(donut_shop).unwrap();\n\nassert_relative_eq!(result.x(), 158458.67251293268);\nassert_relative_eq!(result.y(), -434296.8803996085);\n```\n\n### Integration with `geo-types`\n\nIf you've enabled the `geo-types` feature, you can skip allocating an intermediate representation,\nand pass the [`geo-types`](https://crates.io/crates/geo-types) directly.\n\n```rust\nuse approx::assert_relative_eq;\nuse proj::Proj;\nuse geo_types::Point;\n\nlet my_point = Point::new(4760096.421921f64, 3744293.729449f64);\n\nlet from = \"EPSG:2230\";\nlet to = \"EPSG:26946\";\nlet nad_ft_to_m = Proj::new_known_crs(\u0026from, \u0026to, None).unwrap();\n\nlet result = nad_ft_to_m.convert(my_point).unwrap();\n\nassert_relative_eq!(result.x(), 1450880.2910605003f64);\nassert_relative_eq!(result.y(), 1141263.0111604529f64);\n```\n\nYou can also transform entire geometries from `geo-types` by using the\n`Transform` trait.\n\n```rust\nuse proj::{Proj, Transform};\nuse geo_types::{Coordinate, line_string};\n\nlet line = line_string![\n    (x: -116.590457069172_f64, y: 32.55730630167689),\n    (x: -116.590411068973, y: 32.55714830169309),\n];\nlet proj = Proj::new_known_crs(\"EPSG:4326\", \"EPSG:6366\", None).unwrap();\n\n// create a new line with a different projection\nlet new_line = line.transformed(\u0026proj).unwrap();\n\nassert_eq!(new_line[0], Coordinate { x: 538447.8454476658, y: 3602285.563945497, });\nassert_eq!(new_line[1], Coordinate { x: 538452.2313532799, y: 3602268.065714932, });\n\n// or transform the original in-place\nlet mut line = line;\nline.transform(\u0026proj).unwrap();\n\nassert_eq!(line[0], Coordinate { x: 538447.8454476658, y: 3602285.563945497, });\nassert_eq!(line[1], Coordinate { x: 538452.2313532799, y: 3602268.065714932, });\n```\n\nLicense: MIT/Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorust%2Fproj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeorust%2Fproj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorust%2Fproj/lists"}