如何将 shapefile 中的形状值转换为 JSON 字符串?

问题描述 投票:0回答:1

我正在尝试从

Shape
转换为 JSON 字符串,但我无法为
Polygon
创建字符串,我进行了搜索,但找不到对我有帮助的东西。

在代码中显示了与多边形

bbox
rings
不同的其他类型,但是使用这些类型我无法获得多边形的结构

函数的完整代码

[dependencies]
shapefile = "0.6"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
use shapefile::{ShapeReader, Shape,  Polygon};
use serde_json::to_string;
use serde::Serialize;

fn shapes_to_json(path: &str) -> String {
    let mut reader = match ShapeReader::from_path(path) {
        Ok(reader) => reader,
        Err(_) => return String::new(),
    };

    let mut geometries = Vec::new();

    for shape in reader.iter_shapes() {
        match shape {
            Ok(Shape::Point(point)) => {
                geometries.push(Geometry::Point {
                    coordinates: [point.x, point.y],
                });
            },
            Ok(Shape::Polyline(polyline)) => {
                let parts: Vec<Vec<[f64; 2]>> = polyline.parts().iter().map(|part| {
                    part.iter().map(|p| [p.x, p.y]).collect()
                }).collect();
                geometries.push(Geometry::LineString {
                    coordinates: parts.concat(),
                });
            },
            /// The error is here
            Ok(Shape::Polygon(Polygon { points, parts })) => {
                geometries.push(Geometry::Polygon {
                    coordinates: parts_to_coords(&parts, &points),
                });
            },
            Err(_) => continue, // Skip or log errors
            _ => {} // Optionally handle or skip other geometry types
        }
    }

    // Convert the vector of geometries to JSON string
    to_string(&geometries).unwrap_or_else(|_| String::new())
}

来自 RUST 控制台的消息错误:

error[E0026]: struct `GenericPolygon` does not have fields named `points`, `parts`
  --> src/main.rs:94:41
   |
94 |             Ok(Shape::Polygon(Polygon { points, parts })) => {
   |                                         ^^^^^^  ^^^^^ struct `GenericPolygon` does not have these fields

error: pattern requires `..` due to inaccessible fields
  --> src/main.rs:94:31
   |
94 |             Ok(Shape::Polygon(Polygon { points, parts })) => {
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
help: ignore the inaccessible and unused fields
   |
94 |             Ok(Shape::Polygon(Polygon { points, parts, .. })) => {
   |                                                      ++++

error[E0425]: cannot find function `parts_to_coords` in this scope
  --> src/main.rs:96:34
   |
96 |                     coordinates: parts_to_coords(&parts, &points),
   |                                  ^^^^^^^^^^^^^^^ not found in this scope

可选

我正在尝试使用此库从形状文件中提取 JSON,但如果您知道提取 JSON 的其他方法,请分享给我,我可以测试 😉

rust geojson shapefile
1个回答
0
投票

几个月后我可以找到解决方案:

多边形有一个名为 .rings() 的方法,它具有多边形的所有坐标,虽然延迟且烦人,但我可以:)

use shapefile::{ShapeReader, Shape,  Polygon};
use serde_json::to_string;
use serde::Serialize;

#[derive(Serialize)]
#[serde(tag = "type")]
pub enum Geometry {
    Point {
        coordinates: [f64; 2],
    },
    Polygon {
        coordinates: Vec<Vec<[f64; 2]>>,
    },
    LineString {
        coordinates: Vec<[f64; 2]>,
    },
}

fn shapes_to_json(path: &str) -> String {
    let mut reader = match ShapeReader::from_path(path) {
        Ok(reader) => reader,
        Err(_) => return String::new(),
    };

    let mut geometries = Vec::new();

    for shape in reader.iter_shapes() {
        match shape {
            Ok(Shape::Point(point)) => {
                geometries.push(Geometry::Point {
                    coordinates: [point.x, point.y],
                });
            },
            Ok(Shape::Polyline(polyline)) => {
                let parts: Vec<Vec<[f64; 2]>> = polyline.parts().iter().map(|part| {
                    part.iter().map(|p| [p.x, p.y]).collect()
                }).collect();
                geometries.push(Geometry::LineString {
                    coordinates: parts.concat(),
                });
            },
            /// The error is here
            Ok(Shape::Polygon(polygon)) => {                
                let mut geometry:Vec<Vec<[f64; 2]>> = Vec::new();
                for ring in polygon.rings() {
                    let mut index:usize=0;
                    let mut sub_geometry:Vec<[f64; 2]> = Vec::new();
                    loop {                        
                        let coordinates:[f64; 2] = [ring[index].x, ring[index].y];
                        sub_geometry.push(coordinates);
                        if index+1 == ring.len() {
                            break;
                        }
                        index += 1;
                    };
                    geometry.push(sub_geometry);
                    
                }

                geometries.push(Geometry::Polygon {
                    coordinates: geometry
                });
                continue;
            },
            Err(_) => continue, // Skip or log errors
            _ => {} // Optionally handle or skip other geometry types
        }
    }

    // Convert the vector of geometries to JSON string
    to_string(&geometries).unwrap_or_else(|_| String::new())
}
``
© www.soinside.com 2019 - 2024. All rights reserved.