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};