-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8b8897a
commit 09ddc45
Showing
9 changed files
with
309 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
use anyhow::Result; | ||
use byteorder::{LittleEndian as LE, ReadBytesExt}; | ||
use std::io::Read; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct ReducedElevation { | ||
pub min: i16, | ||
pub avg: i16, | ||
pub max: i16, | ||
} | ||
|
||
impl ReducedElevation { | ||
pub fn from_reader<R: Read>(mut rdr: R) -> Result<Self> { | ||
let mut buf = [0_u8; 3 * std::mem::size_of::<i16>()]; | ||
rdr.read_exact(&mut buf)?; | ||
let rdr = &mut &buf[..]; | ||
let min = rdr.read_i16::<LE>()?; | ||
let avg = rdr.read_i16::<LE>()?; | ||
let max = rdr.read_i16::<LE>()?; | ||
Ok(Self { min, avg, max }) | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct IntermediateElevation { | ||
pub min: i16, | ||
pub sum: i32, | ||
pub max: i16, | ||
pub n: usize, | ||
} | ||
|
||
impl IntermediateElevation { | ||
pub fn reduce(&self) -> ReducedElevation { | ||
let min = self.min; | ||
let avg = i16::try_from(self.sum / i32::try_from(self.n).unwrap()).unwrap(); | ||
let max = self.max; | ||
assert!(min <= avg && avg <= max); | ||
ReducedElevation { min, avg, max } | ||
} | ||
} | ||
|
||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
pub enum Elevation { | ||
Plain(i16), | ||
Intermediate(IntermediateElevation), | ||
} | ||
|
||
impl Elevation { | ||
pub fn concat(source_resolution: u8, this_resolution: u8, items: &[Self]) -> Self { | ||
let mut new_min = i16::MAX; | ||
let mut new_sum: i32 = 0; | ||
let mut new_max = i16::MIN; | ||
let mut new_n = 0_usize; | ||
for item in items { | ||
match item { | ||
Elevation::Plain(elev) => { | ||
let n = 7_usize.pow(u32::from(source_resolution - this_resolution - 1)); | ||
assert_ne!(n, 0); | ||
let sum = i32::from(*elev) * i32::try_from(n).unwrap(); | ||
new_sum += sum; | ||
new_min = i16::min(new_min, *elev); | ||
new_max = i16::max(new_max, *elev); | ||
new_n += n; | ||
} | ||
|
||
Elevation::Intermediate(IntermediateElevation { min, sum, max, n }) => { | ||
new_sum += *sum; | ||
new_min = i16::min(new_min, *min); | ||
new_max = i16::max(new_max, *max); | ||
new_n += n; | ||
} | ||
} | ||
} | ||
Elevation::Intermediate(IntermediateElevation { | ||
min: new_min, | ||
sum: new_sum, | ||
max: new_max, | ||
n: new_n, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use crate::{elevation::ReducedElevation, mask, options::Json}; | ||
use anyhow::Result; | ||
use geo::geometry::GeometryCollection; | ||
use h3o::{ | ||
geom::{PolyfillConfig, ToCells}, | ||
Resolution, | ||
}; | ||
use hextree::{disktree::DiskTree, Cell, HexTreeMap}; | ||
use serde::Serialize; | ||
use serde_json::{json, Value}; | ||
use std::fs::File; | ||
|
||
impl Json { | ||
pub fn run(&self) -> Result<()> { | ||
let mut disktree = DiskTree::open(&self.disktree)?; | ||
let mask = mask::open(Some(&self.mask))?.unwrap(); | ||
let target_cells = Self::polyfill_mask(mask, self.source_resolution)?; | ||
let mut hextree = HexTreeMap::new(); | ||
for h3idx in target_cells { | ||
let cell = Cell::try_from(h3idx)?; | ||
if let Some((cell, reduction)) = Self::get(cell, &mut disktree)? { | ||
hextree.insert(cell, reduction); | ||
} | ||
} | ||
let json = Self::gen_json(&hextree); | ||
Self::output_json(&json)?; | ||
Ok(()) | ||
} | ||
|
||
fn polyfill_mask(mask: GeometryCollection, resolution: Resolution) -> Result<Vec<u64>> { | ||
let polygon = h3o::geom::GeometryCollection::from_degrees(mask)?; | ||
let mut cells: Vec<u64> = polygon | ||
.to_cells(PolyfillConfig::new(resolution)) | ||
.map(u64::from) | ||
.collect(); | ||
cells.sort_unstable(); | ||
cells.dedup(); | ||
Ok(cells) | ||
} | ||
|
||
fn get(cell: Cell, disktree: &mut DiskTree<File>) -> Result<Option<(Cell, ReducedElevation)>> { | ||
match disktree.seek_to_cell(cell)? { | ||
None => Ok(None), | ||
Some((cell, rdr)) => { | ||
let reduction = ReducedElevation::from_reader(rdr)?; | ||
Ok(Some((cell, reduction))) | ||
} | ||
} | ||
} | ||
|
||
fn gen_json(hextree: &HexTreeMap<ReducedElevation>) -> Value { | ||
#[derive(Serialize)] | ||
struct JsonEntry { | ||
h3_id: String, | ||
min: i16, | ||
avg: i16, | ||
max: i16, | ||
} | ||
impl From<(Cell, &ReducedElevation)> for JsonEntry { | ||
fn from((cell, reduction): (Cell, &ReducedElevation)) -> JsonEntry { | ||
JsonEntry { | ||
h3_id: cell.to_string(), | ||
min: reduction.min, | ||
avg: reduction.avg, | ||
max: reduction.max, | ||
} | ||
} | ||
} | ||
let samples = hextree.iter().map(JsonEntry::from).collect::<Vec<_>>(); | ||
json!(samples) | ||
} | ||
|
||
fn output_json(json: &Value) -> Result<()> { | ||
let out = std::io::stdout(); | ||
serde_json::to_writer(out, json)?; | ||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.