Rust GIS数据处理库shapefile的使用,高效读写和操作ESRI Shapefile格式的地理空间数据
Rust GIS数据处理库shapefile的使用,高效读写和操作ESRI Shapefile格式的地理空间数据
基本用法示例
// 创建Shapefile读取器
let mut reader = shapefile::Reader::from_path(filename).unwrap();
// 遍历所有形状和记录
for result in reader.iter_shapes_and_records() {
let (shape, record) = result.unwrap();
println!("Shape: {}, records: ", shape);
// 打印每条记录
for (name, value) in record {
println!("\t{}: {:?}, ", name, value);
}
println!();
}
完整示例代码
use shapefile::{Reader, Shape};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 指定Shapefile文件路径
let filename = "path/to/your/shapefile.shp";
// 创建Shapefile读取器
let mut reader = Reader::from_path(filename)?;
// 获取Shapefile的类型信息
let shape_type = reader.header().shape_type;
println!("Shapefile类型: {:?}", shape_type);
// 遍历所有形状和属性记录
for result in reader.iter_shapes_and_records() {
let (shape, record) = result?;
match shape {
Shape::Point(point) => {
println!("点: ({}, {})", point.x, point.y);
}
Shape::Polyline(polyline) => {
println!("多段线,共{}部分", polyline.parts.len());
for part in &polyline.parts {
println!(" - 部分有{}个点", part.len());
}
}
Shape::Polygon(polygon) => {
println!("多边形,共{}部分", polygon.parts.len());
for part in &polygon.parts {
println!(" - 部分有{}个点", part.len());
}
}
_ => println!("其他形状类型: {:?}", shape),
}
// 打印属性记录
println!("属性记录:");
for (field_name, field_value) in record {
println!(" {}: {:?}", field_name, field_value);
}
println!("------------------");
}
Ok(())
}
安装
在项目中添加shapefile依赖,在Cargo.toml中添加:
shapefile = "0.7.0"
或者运行命令:
cargo add shapefile
特性
- 支持读取和写入ESRI Shapefile格式
- 通过dbase crate支持.dbf属性表
- 支持多种几何类型:点、线、多边形等
- 提供迭代器接口方便遍历要素
1 回复
下面是根据提供的内容整理的完整示例代码,包含形状文件的读取、写入以及属性数据处理:
完整示例:城市点数据Shapefile处理
use shapefile::{Point, Shape, ShapeReader, ShapeWriter};
use shapefile::dbase::{FieldName, FieldValue, FieldType, Record, TableWriterBuilder};
fn main() -> Result<(), shapefile::Error> {
// 示例1:读取并打印城市点数据
read_city_points()?;
// 示例2:创建带属性的城市Shapefile
create_city_shapefile_with_attributes()?;
// 示例3:批量生成并写入大量点数据
batch_generate_points()?;
Ok(())
}
/// 示例1:读取城市点数据并打印信息
fn read_city_points() -> Result<(), shapefile::Error> {
println!("\n--- 读取城市点数据 ---");
// 读取Shapefile和对应的DBF文件
let mut reader = ShapeReader::from_path("data/cities.shp")?;
let shapes = reader.read_shapes()?;
let records = reader.read_records()?;
// 关联几何图形和属性数据
for (shape, record) in shapes.iter().zip(records.iter()) {
if let Shape::Point(point) = shape {
if let Some(name) = record.get("NAME") {
println!("城市: {}, 坐标: ({}, {})", name, point.x, point.y);
}
}
}
Ok(())
}
/// 示例2:创建带属性的城市Shapefile
fn create_city_shapefile_with_attributes() -> Result<(), shapefile::Error> {
println!("\n--- 创建带属性的城市Shapefile ---");
// 创建几何数据 - 两个城市点
let points = vec![
Shape::Point(Point::new(116.404, 39.915)), // 北京
Shape::Point(Point::new(121.474, 31.230)), // 上海
];
// 创建属性字段
let name_field = FieldName::try_from("NAME")?;
let pop_field = FieldName::try_from("POPULATION")?;
let province_field = FieldName::try_from("PROVINCE")?;
// 创建属性记录
let records = vec![
Record::from_data(vec![
(name_field.clone(), FieldValue::Character(Some("Beijing".to_string()))),
(pop_field.clone(), FieldValue::Numeric(Some(2171.0))), // 万人
(province_field.clone(), FieldValue::Character(Some("Beijing".to_string()))),
]),
Record::from_data(vec![
(name_field.clone(), FieldValue::Character(Some("Shanghai".to_string()))),
(pop_field.clone(), FieldValue::Numeric(Some(2424.0))), // 万人
(province_field.clone(), FieldValue::Character(Some("Shanghai".to_string()))),
]),
];
// 创建Shapefile写入器
let mut shape_writer = ShapeWriter::from_path("output/china_cities.shp")?;
for point in &points {
shape_writer.write_shape(point)?;
}
// 创建DBF表写入器
let mut table_writer = TableWriterBuilder::new()
.add_field(name_field, FieldType::Character(50)) // 城市名称字段
.add_field(pop_field, FieldType::Float) // 人口数字段
.add_field(province_field, FieldType::Character(20)) // 省份字段
.build_with_dbf_path("output/china_cities.dbf")?;
for record in &records {
table_writer.write_record(record)?;
}
println!("成功创建带属性的城市Shapefile");
Ok(())
}
/// 示例3:批量生成并写入大量点数据
fn batch_generate_points() -> Result<(), shapefile::Error> {
println!("\n--- 批量生成点数据 ---");
let mut writer = ShapeWriter::from_path("output/random_points.shp")?;
let mut shapes = Vec::new();
// 生成1000个随机点
for i in 0..1000 {
shapes.push(Shape::Point(Point::new(
rand::random::<f64>() * 360.0 - 180.0, // 经度 -180到180
rand::random::<f64>() * 180.0 - 90.0 // 纬度 -90到90
)));
}
// 批量写入
writer.write_shapes(&shapes)?;
println!("成功生成1000个随机点数据");
Ok(())
}
示例说明
-
读取城市点数据:
- 从"data/cities.shp"读取点数据
- 同时读取关联的.dbf属性表
- 打印每个城市的名称和坐标
-
创建带属性的城市Shapefile:
- 创建北京和上海两个城市的点数据
- 为每个城市添加名称、人口和省份属性
- 同时生成.shp和.dbf文件
-
批量生成点数据:
- 生成1000个随机地理坐标点
- 使用批量写入提高性能
- 保存到random_points.shp文件
运行准备
- 创建Cargo项目并添加依赖:
[dependencies]
shapefile = "0.4.0"
rand = "0.8"
-
创建data目录并放入测试数据(如cities.shp等)
-
创建output目录用于保存生成的文件
这个完整示例展示了shapefile库的主要功能,包括数据读取、属性处理和批量写入操作,适用于大多数GIS数据处理场景。