I'm trying to convert from Shape
to a JSON string but I couldn't create a string for Polygon
, I searched but I couldn't find something that helps me.
In the code shows other types different to polygon bbox
and rings
, but with these types I can't get structure of polygon
[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())
}
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
I'm trying extract the JSON from shape file with this library, but if you know others ways for extract the JSON share me that and I can test 😉
Later of months I could find the solution:
The polygon has a method called .rings() that has all coordinates of polygon, was delay and annoying but I can :)
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())
}
``