Rust地理空间坐标转换库proj-sys的使用,proj-sys提供高效PROJ投影系统绑定与坐标转换功能
Rust地理空间坐标转换库proj-sys的使用,proj-sys提供高效PROJ投影系统绑定与坐标转换功能
proj-sys是PROJ v9.6.x的低级绑定库,属于*-sys
类型的crate,不建议直接使用其API。对于一般用途,请使用proj
crate。
特性
bundled_proj
- 强制从源码构建libproj,即使系统上已有可接受的版本。注意:使用此功能需要系统安装SQLite3,且构建的libproj
不包含其原生网络功能bundled_proj_tiff
- 如果启用了bundled_proj
功能,添加此功能将构建支持TIFF的PROJ。注意:需要系统安装libtiff
许可证
可选择以下任一种:
- Apache License, Version 2.0
- MIT license
示例使用
以下是一个使用proj-sys进行坐标转换的完整示例:
use proj_sys::*;
fn main() {
// 初始化PROJ上下文
let ctx = unsafe { proj_context_create() };
// 创建坐标转换对象:从WGS84(经度/纬度)到Web墨卡托投影
let wgs84_to_mercator = unsafe {
proj_create_crs_to_crs(
ctx,
"+proj=longlat +datum=WGS84 +no_defs".as_ptr() as *const i8,
"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs".as_ptr() as *const i8,
std::ptr::null(),
)
};
if wgs84_to_mercator.is_null() {
eprintln!("无法创建坐标转换对象");
return;
}
// 创建坐标点(伦敦的经度/纬度)
let mut coord = PJ_COORD {
xyzt: [51.5074, -0.1278, 0.0, 0.0],
};
// 执行坐标转换
let result = unsafe { proj_trans(wgs84_to_mercator, PJ_FWD, coord) };
// 输出转换后的坐标(Web墨卡托投影)
println!("转换后坐标: X={}, Y={}", result.xyzt[0], result.xyzt[1]);
// 清理资源
unsafe {
proj_destroy(wgs84_to_mercator);
proj_context_destroy(ctx);
}
}
完整示例代码
以下是一个更完整的示例,演示如何使用proj-sys进行多种坐标转换:
use proj_sys::*;
fn main() {
// 初始化PROJ上下文
let ctx = unsafe { proj_context_create() };
// 示例1: WGS84转Web墨卡托投影
println!("示例1: WGS84转Web墨卡托投影");
transform_coordinates(
ctx,
"+proj=longlat +datum=WGS84 +no_defs", // WGS84坐标系统
"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs", // Web墨卡托投影
[51.5074, -0.1278, 0.0, 0.0], // 伦敦坐标(纬度,经度)
);
// 示例2: WGS84转UTM投影
println!("\n示例2: WGS84转UTM投影(北半球50区)");
transform_coordinates(
ctx,
"+proj=longlat +datum=WGS84 +no_defs",
"+proj=utm +zone=50 +datum=WGS84 +units=m +no_defs", // UTM 50N投影
[39.9042, 116.4074, 0.0, 0.0], // 北京坐标
);
// 清理上下文
unsafe { proj_context_destroy(ctx) };
}
/// 通用坐标转换函数
fn transform_coordinates(ctx: *mut PJ_CONTEXT, src_crs: &str, dst_crs: &str, coords: [f64; 4]) {
// 创建坐标转换对象
let transformation = unsafe {
proj_create_crs_to_crs(
ctx,
src_crs.as_ptr() as *const i8,
dst_crs.as_ptr() as *const i8,
std::ptr::null(),
)
};
if transformation.is_null() {
eprintln!("无法创建坐标转换对象");
return;
}
// 创建坐标点
let mut coord = PJ_COORD { xyzt: coords };
// 执行正向转换
let result = unsafe { proj_trans(transformation, PJ_FWD, coord) };
// 输出结果
println!("原始坐标: 纬度={}, 经度={}", coords[0], coords[1]);
println!("转换后坐标: X={:.2}, Y={:.2}", result.xyzt[0], result.xyzt[1]);
// 清理转换对象
unsafe { proj_destroy(transformation) };
}
安装
在项目目录中运行以下Cargo命令:
cargo add proj-sys
或在Cargo.toml中添加:
proj-sys = "0.26.0"
1 回复
Rust地理空间坐标转换库proj-sys使用指南
proj-sys
是Rust语言对PROJ库的绑定,PROJ是一个广泛使用的地理空间坐标转换库,支持各种地图投影和坐标参考系统(CRS)之间的转换。
主要功能
- 支持2000多种坐标参考系统(CRS)
- 支持多种地图投影转换
- 支持大地基准面转换
- 提供高效的地理空间坐标转换能力
安装方法
在Cargo.toml中添加依赖:
[dependencies]
proj-sys = "0.24"
基本使用方法
1. 创建转换器
use proj_sys::Proj;
fn main() {
// 创建从WGS84(EPSG:4326)到Web墨卡托(EPSG:3857)的转换器
let proj = Proj::new(
"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs",
"+proj=longlat +datum=WGS84 +no_defs"
).unwrap();
}
2. 坐标转换示例
use proj_sys::Proj;
fn main() {
let proj = Proj::new(
"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs",
"+proj=longlat +datum=WGS84 +no_defs"
).unwrap();
// 转换单个坐标点
let result = proj.project((2.0, 1.0), false).unwrap();
println!("转换结果: {:?}", result); // (x, y)坐标
// 批量转换坐标
let coords = vec![(2.0, 1.0), (3.0, 4.0)];
let results: Vec<_> = coords.iter()
.map(|&(x, y)| proj.project((x, y), false).unwrap())
.collect();
println!("批量转换结果: {:?}", results);
}
3. 使用EPSG代码创建转换器
use proj_sys::Proj;
fn main() {
// 从EPSG:4326(WGS84)到EPSG:32651(UTM zone 51N)
let proj = Proj::new_known_crs("EPSG:32651", "EPSG:4326", None).unwrap();
let beijing = (116.4074, 39.9042); // 北京经纬度
let result = proj.project(beijing, false).unwrap();
println!("北京在UTM zone 51N中的坐标: {:?}", result);
}
高级用法
1. 错误处理
use proj_sys::{Proj, ProjError};
fn try_project() -> Result<(), ProjError> {
let proj = Proj::new_known_crs("EPSG:3857", "EPSG:4326", None)?;
let result = proj.project((181.极好,以下是一个完整的proj-sys使用示例,结合了上述所有功能点:
```rust
use proj_sys::{Proj, ProjError};
use rayon::prelude::*;
fn main() -> Result<(), ProjError> {
// 1. 创建转换器 (WGS84到Web墨卡托)
let proj = Proj::new_known_crs("EPSG:3857", "EPSG:4326", None)?;
// 2. 单个坐标转换
let shanghai = (121.4737, 31.2304);
let projected = proj.project(shanghai, false)?;
println!("上海坐标(Web墨卡托): {:?}", projected);
// 3. 反向转换验证
let inverse = proj.project(projected, true)?;
println!("反向转换结果: {:?}", inverse);
// 4. 批量转换示例
let cities = vec![
(116.4074, 39.9042), // 北京
(121.4737, 31.2304), // 上海
(113.2644, 23.1291), // 广州
];
// 单线程批量转换
let results: Vec<_> = cities.iter()
.map(|&coord| proj.project(coord, false))
.collect::<Result<_, _>>()?;
println!("单线程批量结果: {:?}", results);
// 5. 使用rayon并行处理
let par_results: Vec<_> = cities.par_iter()
.map(|&coord| proj.project(coord, false))
.collect::<Result<_, _>>()?;
println!("并行处理结果: {:?}", par_results);
// 6. 错误处理示例
match proj.project((181.0, 91.0), false) {
Ok(_) => unreachable!(),
Err(e) => println!("捕获到预期错误: {}", e),
}
Ok(())
}
这个完整示例展示了:
- 使用EPSG代码创建转换器
- 单个坐标的正向转换
- 反向转换验证
- 批量坐标转换
- 使用rayon的并行处理
- 错误处理机制
要运行此示例,需要在Cargo.toml中添加:
[dependencies]
proj-sys = "0.24"
rayon = "1.5"