use anyhow::{Context, Result as AnyResult};
use clap::{Parser, ValueEnum};
use geojson::{FeatureCollection, GeoJson};
use h3o::CellIndex;
use kml::Kml;
#[derive(Parser, Debug)]
pub struct Args {
#[arg(short, long)]
index: Option<CellIndex>,
#[arg(short, long, value_enum, default_value_t = Format::Text)]
format: Format,
#[arg(short, long, default_value_t = false)]
pretty: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueEnum)]
enum Format {
Text,
Geojson,
Kml,
}
pub fn run(args: &Args) -> AnyResult<()> {
let indexes = crate::utils::get_cell_indexes(args.index);
match args.format {
Format::Text => boundaries_to_text(indexes),
Format::Geojson => boundaries_to_geojson(indexes, args.pretty),
Format::Kml => boundaries_to_kml(indexes),
}
.context("cellToBoundary")?;
Ok(())
}
fn boundaries_to_text(
indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
) -> AnyResult<()> {
for index in indexes {
let index = index?;
println!("{index}");
println!("{{");
for ll in &*index.boundary() {
println!(" {:.9} {:.9}", ll.lat(), ll.lng());
}
println!("}}");
}
Ok(())
}
fn boundaries_to_geojson(
indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
pretty: bool,
) -> AnyResult<()> {
let indexes = indexes.into_iter().collect::<AnyResult<Vec<_>>>()?;
let features = crate::geojson::boundaries(&indexes);
let geojson = GeoJson::FeatureCollection(FeatureCollection {
bbox: None,
features,
foreign_members: None,
});
crate::json::print(&geojson, pretty)
}
fn boundaries_to_kml(
indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
) -> AnyResult<()> {
let indexes = indexes.into_iter().collect::<AnyResult<Vec<_>>>()?;
let style_id = "lineStyle1";
let style = kml::types::Style {
id: Some(style_id.to_owned()),
line: Some(kml::types::LineStyle {
id: Some("lineStyle2".to_owned()),
color: "ff0000ff".to_owned(),
width: 2.,
..kml::types::LineStyle::default()
}),
..kml::types::Style::default()
};
let mut elements = vec![Kml::Style(style)];
elements.append(&mut crate::kml::boundaries(&indexes, style_id));
crate::kml::print_document(
"H3 Geometry".to_owned(),
"Generated by cellToBoundary".to_owned(),
elements,
)
}