h3o_cli/commands/
cell_to_latlng.rs1use anyhow::{Context, Result as AnyResult};
4use clap::{Parser, ValueEnum};
5use geojson::{FeatureCollection, GeoJson};
6use h3o::{CellIndex, LatLng};
7use kml::Kml;
8
9#[derive(Parser, Debug)]
14pub struct Args {
15 #[arg(short, long)]
17 index: Option<CellIndex>,
18
19 #[arg(short, long, value_enum, default_value_t = Format::Text)]
21 format: Format,
22
23 #[arg(short, long, default_value_t = false)]
25 pretty: bool,
26}
27
28#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueEnum)]
29enum Format {
30 Text,
31 Json,
32 Geojson,
33 Kml,
34}
35
36pub fn run(args: &Args) -> AnyResult<()> {
38 let indexes = crate::utils::get_cell_indexes(args.index);
39
40 match args.format {
41 Format::Text => latlng_to_text(indexes),
42 Format::Json => latlng_to_json(indexes, args.pretty),
43 Format::Geojson => latlng_to_geojson(indexes, args.pretty),
44 Format::Kml => latlng_to_kml(indexes),
45 }
46 .context("cellToLatLng")?;
47
48 Ok(())
49}
50
51fn latlng_to_text(
53 indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
54) -> AnyResult<()> {
55 for ll in indexes.into_iter().map(|input| input.map(LatLng::from)) {
56 let ll = ll?;
57 println!("{:.9} {:.9}", ll.lat(), ll.lng());
58 }
59
60 Ok(())
61}
62
63fn latlng_to_json(
65 indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
66 pretty: bool,
67) -> AnyResult<()> {
68 let coords = indexes
69 .into_iter()
70 .map(|input| input.map(LatLng::from))
71 .collect::<AnyResult<Vec<_>>>()?;
72
73 crate::json::print(&coords, pretty)
74}
75
76fn latlng_to_geojson(
78 indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
79 pretty: bool,
80) -> AnyResult<()> {
81 let indexes = indexes.into_iter().collect::<AnyResult<Vec<_>>>()?;
82 let features = crate::geojson::centers(&indexes);
83 let geojson = GeoJson::FeatureCollection(FeatureCollection {
84 bbox: None,
85 features,
86 foreign_members: None,
87 });
88
89 crate::json::print(&geojson, pretty)
90}
91
92fn latlng_to_kml(
94 indexes: impl IntoIterator<Item = AnyResult<CellIndex>>,
95) -> AnyResult<()> {
96 let indexes = indexes.into_iter().collect::<AnyResult<Vec<_>>>()?;
97 let style = kml::types::Style {
99 id: Some("s_circle".to_owned()),
100 icon: Some(kml::types::IconStyle{
101 scale: 1.1,
102 icon: kml::types::Icon {
103 href: "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png".to_owned(),
104 ..kml::types::Icon::default()
105 },
106 hot_spot: Some(kml::types::Vec2 {
107 x: 20.,
108 y: 2.,
109 xunits: kml::types::Units::Pixels,
110 yunits: kml::types::Units::Pixels,
111 }),
112 ..kml::types::IconStyle::default()
113 }),
114 label: Some(kml::types::LabelStyle{
115 color: "ff0000ff".to_owned(),
116 scale: 2.,
117 ..kml::types::LabelStyle::default()
118 }),
119 ..kml::types::Style::default()
120 };
121 let style_hl = kml::types::Style {
122 id: Some("s_circle_hl".to_owned()),
123 icon: Some(kml::types::IconStyle{
124 scale: 1.3,
125 icon: kml::types::Icon {
126 href: "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png".to_owned(),
127 ..kml::types::Icon::default()
128 },
129 hot_spot: Some(kml::types::Vec2 {
130 x: 20.,
131 y: 2.,
132 xunits: kml::types::Units::Pixels,
133 yunits: kml::types::Units::Pixels,
134 }),
135 ..kml::types::IconStyle::default()
136 }),
137 label: Some(kml::types::LabelStyle{
138 color: "ff0000ff".to_owned(),
139 scale: 2.,
140 ..kml::types::LabelStyle::default()
141 }),
142 ..kml::types::Style::default()
143 };
144 let style_id = "m_ylw-pushpin";
145 let style_map = kml::types::StyleMap {
146 id: Some(style_id.to_owned()),
147 pairs: vec![
148 kml::types::Pair {
149 key: "normal".to_owned(),
150 style_url: "#s_circle".to_owned(),
151 ..kml::types::Pair::default()
152 },
153 kml::types::Pair {
154 key: "highlight".to_owned(),
155 style_url: "#s_circle_hl".to_owned(),
156 ..kml::types::Pair::default()
157 },
158 ],
159 ..kml::types::StyleMap::default()
160 };
161 let mut elements = vec![
162 Kml::Style(style),
163 Kml::Style(style_hl),
164 Kml::StyleMap(style_map),
165 ];
166 elements.append(&mut crate::kml::centers(&indexes, style_id));
167
168 crate::kml::print_document(
169 "H3 Geometry".to_owned(),
170 "Generated by cellToLatLng".to_owned(),
171 elements,
172 )
173}