Skip to main content

geometry_io_geojson/
lib.rs

1//! RFC 7946 `GeoJSON` reader and writer.
2//!
3//! Not part of Boost.Geometry; follows RFC 7946. The parser emits a
4//! [`geometry_model::DynGeometry`] (a `GeoJSON` `GeometryCollection` is
5//! heterogeneous); the writer serialises concrete model geometries with
6//! [`to_geojson`] and any user-defined polygon implementing the geometry
7//! traits with [`to_geojson_polygon`]. Feature objects and property bags
8//! are out of scope — only the `geometry` member's OGC-equivalent kinds.
9//!
10//! ## Serialize a user-defined polygon
11//!
12//! Application types can implement the lightweight [`geometry_trait`] traits
13//! directly; they do not need to be converted to a `geometry_model` polygon.
14//!
15//! ```
16//! use geometry_cs::Cartesian;
17//! use geometry_io_geojson::{from_geojson, to_geojson_polygon};
18//! use geometry_tag::{PointTag, PolygonTag, RingTag};
19//! use geometry_trait::{Geometry, Point, Polygon, Ring};
20//!
21//! struct Coordinate(f64, f64);
22//!
23//! impl Geometry for Coordinate {
24//!     type Kind = PointTag;
25//!     type Point = Self;
26//! }
27//!
28//! impl Point for Coordinate {
29//!     type Scalar = f64;
30//!     type Cs = Cartesian;
31//!     const DIM: usize = 2;
32//!
33//!     fn get<const D: usize>(&self) -> f64 {
34//!         match D {
35//!             0 => self.0,
36//!             1 => self.1,
37//!             _ => unreachable!("a Coordinate has two dimensions"),
38//!         }
39//!     }
40//! }
41//!
42//! struct Boundary(Vec<Coordinate>);
43//!
44//! impl Geometry for Boundary {
45//!     type Kind = RingTag;
46//!     type Point = Coordinate;
47//! }
48//!
49//! impl Ring for Boundary {
50//!     fn points(&self) -> impl ExactSizeIterator<Item = &Coordinate> + Clone {
51//!         self.0.iter()
52//!     }
53//! }
54//!
55//! struct Parcel {
56//!     exterior: Boundary,
57//!     holes: Vec<Boundary>,
58//! }
59//!
60//! impl Geometry for Parcel {
61//!     type Kind = PolygonTag;
62//!     type Point = Coordinate;
63//! }
64//!
65//! impl Polygon for Parcel {
66//!     type Ring = Boundary;
67//!
68//!     fn exterior(&self) -> &Boundary {
69//!         &self.exterior
70//!     }
71//!
72//!     fn interiors(&self) -> impl ExactSizeIterator<Item = &Boundary> {
73//!         self.holes.iter()
74//!     }
75//! }
76//!
77//! let parcel = Parcel {
78//!     exterior: Boundary(vec![
79//!         Coordinate(0.0, 0.0),
80//!         Coordinate(0.0, 2.0),
81//!         Coordinate(2.0, 2.0),
82//!         Coordinate(2.0, 0.0),
83//!         Coordinate(0.0, 0.0),
84//!     ]),
85//!     holes: vec![],
86//! };
87//!
88//! let geojson = to_geojson_polygon(&parcel);
89//! assert_eq!(
90//!     geojson,
91//!     r#"{"type":"Polygon","coordinates":[[[0,0],[0,2],[2,2],[2,0],[0,0]]]}"#
92//! );
93//! assert!(from_geojson(&geojson).is_ok());
94//! ```
95
96#![cfg_attr(not(feature = "std"), no_std)]
97#![forbid(unsafe_code)]
98
99extern crate alloc;
100
101mod json;
102mod parse;
103mod write;
104
105pub use json::GeoJsonError;
106// feature-group: I/O — GeoJSON
107// feature-desc: Parse and write GeoJSON (RFC 7946)
108pub use parse::from_geojson;
109// feature-group: I/O — GeoJSON
110pub use write::{WriteGeoJson, to_geojson, to_geojson_polygon};