gshhg_reader/
lib.rs

1use std::io::{Read,ErrorKind};
2use anyhow::{bail,Result};
3use serde::{Serialize,Deserialize};
4
5pub type PolygonId = usize;
6
7#[derive(Debug,Clone,Serialize,Deserialize,PartialEq)]
8pub enum Level {
9    Land,
10    Lake,
11    IslandInLake,
12    PondInIslandInLake,
13    AntarcticIceFront,
14    AntarcticGroundingLine,
15    Other(u8)
16}
17
18#[derive(Debug,Clone,Serialize,Deserialize,PartialEq)]
19pub enum Source {
20    CiaWdbii,
21    Wvs,
22    Other(u8)
23}
24
25/// Global Self-consistent Hierarchical High-resolution Shorelines
26#[derive(Debug,Clone,Serialize,Deserialize)]
27pub struct Polygon {
28    /// Unique polygon id number, starting at 0
29    pub id:PolygonId,
30
31    /// Number of points in this polygon
32    pub n:usize,
33
34    /// level + version << 8 + greenwich << 16 + source << 24 + river << 25
35    pub level:Level,
36    pub version:u8,
37    pub greenwich_crossed:bool,
38    pub source:Source,
39    pub river:bool,
40
41    /// Min/max extent in micro-degrees
42    pub west:i32,
43    pub east:i32,
44    pub south:i32,
45    pub north:i32,
46
47    /// Area of polygon in 1/10 km^2
48    pub area:u32,
49
50    /// Area of original full-resolution polygon in 1/10 km^2
51    pub area_full:u32,
52
53    /// Id of container polygon that encloses this polygon
54    pub container:Option<PolygonId>,
55
56    /// Id of ancestor polygon in the full resolution set that was the source of this polygon
57    pub ancestor:Option<PolygonId>,
58
59    /// Points of the polygon
60    pub points:Vec<Point>,
61
62    /// Ids of contained polygons
63    pub children:Vec<PolygonId>
64}
65
66/// Each lon, lat pair is stored in micro-degrees in 4-byte signed integer format
67#[derive(Debug,Clone,Serialize,Deserialize)]
68pub struct Point {
69    pub x:i32,
70    pub y:i32
71}
72
73#[derive(Debug,Clone,Serialize,Deserialize)]
74pub struct Gshhg {
75    pub polygons:Vec<Polygon>
76}
77
78fn read_u32<R:Read>(mut r:R)->Result<u32> {
79    let mut x = [0;4];
80    r.read_exact(&mut x)?;
81    Ok(u32::from_be_bytes(x))
82}
83
84fn read_i32<R:Read>(mut r:R)->Result<i32> {
85    let mut x = [0;4];
86    r.read_exact(&mut x)?;
87    Ok(i32::from_be_bytes(x))
88}
89
90fn read_id_option<R:Read>(r:R)->Result<Option<PolygonId>> {
91    let id = read_i32(r)?;
92    if id < 0 {
93	Ok(None)
94    } else {
95	Ok(Some(id as usize))
96    }
97}
98
99impl From<u8> for Level {
100    fn from(x:u8)->Self {
101	match x {
102	    1 => Self::Land,
103	    2 => Self::Lake,
104	    3 => Self::IslandInLake,
105	    4 => Self::PondInIslandInLake,
106	    5 => Self::AntarcticIceFront,
107	    6 => Self::AntarcticGroundingLine,
108	    _ => Self::Other(x)
109	}
110    }
111}
112
113impl From<u8> for Source {
114    fn from(x:u8)->Self {
115	match x {
116	    0 => Self::CiaWdbii,
117	    1 => Self::Wvs,
118	    _ => Self::Other(x)
119	}
120    }
121}
122
123impl Point {
124    pub fn from_reader<R:Read>(mut r:R)->Result<Self> {
125	let x = read_i32(&mut r)?;
126	let y = read_i32(&mut r)?;
127	Ok(Self{ x,y })
128    }
129}
130
131impl Polygon {
132    pub fn from_reader<R:Read>(mut r:R,expected_id:Option<PolygonId>)
133			       ->Result<Option<Self>> {
134	let id =
135	    match read_id_option(&mut r) {
136		Ok(Some(id)) => {
137		    if let Some(eid) = expected_id {
138			if eid != id {
139			    bail!("Unexpected polygon ID {} (was expecting {})",
140				  id,eid);
141			}
142		    }
143		    id
144		}
145		Ok(None) => bail!("Invalid polygon ID"),
146		Err(e) => {
147		    if let Some(ed) = e.downcast_ref::<std::io::Error>() {
148			match ed.kind() {
149			    ErrorKind::UnexpectedEof => return Ok(None),
150			    _ => return Err(e)
151			}
152		    }
153		    return Ok(None)
154		}
155	    };
156	let n = read_u32(&mut r)? as usize;
157	let flag = read_u32(&mut r)?;
158
159	let level = Level::from((flag & 255) as u8);
160	let version = ((flag >> 8) & 255) as u8;
161	let greenwich_crossed = ((flag >> 16) & 1) != 0;
162	let source = Source::from(((flag >> 24) & 255) as u8);
163	let river = ((flag >> 24) & 1) != 0;
164	
165	let west = read_i32(&mut r)?;
166	let east = read_i32(&mut r)?;
167	let south = read_i32(&mut r)?;
168	let north = read_i32(&mut r)?;
169	let area = read_u32(&mut r)?;
170	let area_full = read_u32(&mut r)?;
171	let container = read_id_option(&mut r)?;
172	let ancestor = read_id_option(&mut r)?;
173	let mut points = Vec::with_capacity(n);
174	for _ in 0..n {
175	    points.push(Point::from_reader(&mut r)?);
176	}
177	Ok(Some(Self{
178	    id,
179	    n,
180	    level,
181	    version,
182	    greenwich_crossed,
183	    source,
184	    river,
185	    west,
186	    east,
187	    south,
188	    north,
189	    area,
190	    area_full,
191	    container,
192	    ancestor,
193	    points,
194	    children:Vec::new()
195	}))
196    }
197}
198
199impl Gshhg {
200    pub fn from_reader<R:Read>(mut r:R)->Result<Self> {
201	let mut polygons = Vec::new();
202	let mut expected_id = Some(0);
203	loop {
204	    match Polygon::from_reader(&mut r,expected_id)? {
205		Some(poly) => polygons.push(poly),
206		None => break
207	    }
208	    expected_id = None;
209	}
210
211	// Fill in children
212	let npoly = polygons.len();
213	for ipoly in 0..npoly {
214	    if let Some(iparent) = polygons[ipoly].container {
215		polygons[iparent].children.push(ipoly);
216	    }
217	}
218
219	Ok(Self{
220	    polygons
221	})
222    }
223}