Skip to content

Commit 818fdff

Browse files
committed
update precomputed average edge lengths
H3 reference implementation did the same in uber/h3#749 Couldn't test against it since it's not released yet (and thus there is no h3ron_h3_sys that binds to it). Not a big deal since I shouldn't exclusively rely on tests against H3 to ensure my correctness. Instead I have a little tool (which is equivalent to the Python notebook linked in the PR) that generated a golden file and I test against it.
1 parent e424500 commit 818fdff

13 files changed

+159
-178
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ Possible sections are:
1414
<!-- next-header -->
1515
## [Unreleased] - ReleaseDate
1616

17+
### Fixed
18+
19+
- update precomputed average edge lengths (they were underestimated).
20+
1721
## [0.3.4] - 2023-07-28
1822

1923
### Fixed

Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pre-release-replacements = [
2727
default = []
2828
geo = ["dep:geo", "dep:geojson"]
2929
serde = ["dep:serde", "dep:serde_repr"]
30+
tools = ["polyfit-rs"]
3031

3132
[dependencies]
3233
ahash = { version = "0.8", default-features = false, features = ["std", "compile-time-rng"] }
@@ -37,6 +38,7 @@ either = { version = "1.0", default-features = false }
3738
float_eq = { version = "1.0", default-features = false }
3839
geo = { version = "0.26", optional = true, default-features = false }
3940
geojson = { version = "0.24", optional = true, default-features = false, features = ["geo-types"] }
41+
polyfit-rs = { version = "0.2", optional = true, default-features = false }
4042
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
4143
serde_repr = { version = "0.1", optional = true, default-features = false }
4244

@@ -50,6 +52,11 @@ h3ron-h3-sys = { version = "0.16", default-features = false }
5052
# Cf. https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html
5153
doctest = false
5254

55+
[[bin]]
56+
name = "average_edge_length"
57+
path = "tools/average_edge_length.rs"
58+
required-features = ["tools"]
59+
5360
[[bench]]
5461
harness = false
5562
name = "h3"

dataset/avgEdgeLen.txt

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
0.20110729345570325,1281.2560107413644,1281256.0107413644
2+
0.07582111043884765,483.0568390711111,483056.8390711111
3+
0.02864742595735945,182.51295648916735,182512.95648916735
4+
0.01082705133253538,68.97922178775585,68979.22178775584
5+
0.00409225087020209,26.07175968017739,26071.75968017739
6+
0.0015467085046591636,9.854090989971207,9854.090989971206
7+
0.0005846065718298453,3.7245326671400765,3724.5326671400767
8+
0.0002207619176534713,1.4064757626435986,1406.4757626435987
9+
0.0000834113029497395,0.5314140100625567,531.4140100625567
10+
0.00003151560528974152,0.20078614761193547,200.78614761193546
11+
0.000011907659293816194,0.07586378286883358,75.86378286883358
12+
0.000004499115550979479,0.02866389748307224,28.66389748307224
13+
0.000001699917695123959,0.010830187842605124,10.830187842605124
14+
0.0000006422862754806202,0.004092010473292413,4.092010473292413
15+
0.0000002426774312980401,0.001546099657446663,1.546099657446663
16+
0.00000009169172362798202,0.0005841686296646656,0.5841686296646657

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ const CCW: bool = true;
282282
const CW: bool = false;
283283

284284
/// Earth radius in kilometers using WGS84 authalic radius.
285-
const EARTH_RADIUS_KM: f64 = 6371.007180918475_f64;
285+
pub const EARTH_RADIUS_KM: f64 = 6371.007180918475_f64;
286286

287287
/// Number of pentagon per resolution.
288288
const NUM_PENTAGONS: u8 = 12;

src/resolution.rs

+48-48
Original file line numberDiff line numberDiff line change
@@ -241,22 +241,22 @@ impl Resolution {
241241
#[must_use]
242242
pub const fn edge_length_rads(self) -> f64 {
243243
match self {
244-
Self::Zero => 0.17386773543713177,
245-
Self::One => 0.06571582696594004,
246-
Self::Two => 0.024838247910621048,
247-
Self::Three => 0.00938797528264242,
248-
Self::Four => 0.0035483211300887216,
249-
Self::Five => 0.0013411393259123903,
250-
Self::Six => 0.000506903018673795,
251-
Self::Seven => 0.00019159133310284987,
252-
Self::Eight => 7.241471731216742e-5,
253-
Self::Nine => 2.7370188582154633e-5,
254-
Self::Ten => 1.0344958831218647e-5,
255-
Self::Eleven => 3.909987901851459e-6,
256-
Self::Twelve => 1.4778708817343719e-6,
257-
Self::Thirteen => 5.587645562011106e-7,
258-
Self::Fourteen => 2.1167375294114534e-7,
259-
Self::Fifteen => 8.000508954480841e-8,
244+
Self::Zero => 0.20110729345570325,
245+
Self::One => 0.07582111043884765,
246+
Self::Two => 0.02864742595735945,
247+
Self::Three => 0.01082705133253538,
248+
Self::Four => 0.00409225087020209,
249+
Self::Five => 0.0015467085046591636,
250+
Self::Six => 0.0005846065718298453,
251+
Self::Seven => 0.0002207619176534713,
252+
Self::Eight => 0.0000834113029497395,
253+
Self::Nine => 0.00003151560528974152,
254+
Self::Ten => 0.000011907659293816194,
255+
Self::Eleven => 0.000004499115550979479,
256+
Self::Twelve => 0.000001699917695123959,
257+
Self::Thirteen => 0.0000006422862754806202,
258+
Self::Fourteen => 0.0000002426774312980401,
259+
Self::Fifteen => 0.00000009169172362798202,
260260
}
261261
}
262262

@@ -271,22 +271,22 @@ impl Resolution {
271271
#[must_use]
272272
pub const fn edge_length_km(self) -> f64 {
273273
match self {
274-
Self::Zero => 1107.712591,
275-
Self::One => 418.6760055,
276-
Self::Two => 158.2446558,
277-
Self::Three => 59.81085794,
278-
Self::Four => 22.6063794,
279-
Self::Five => 8.544408276,
280-
Self::Six => 3.229482772,
281-
Self::Seven => 1.220629759,
282-
Self::Eight => 0.461354684,
283-
Self::Nine => 0.174375668,
284-
Self::Ten => 0.065907807,
285-
Self::Eleven => 0.024910561,
286-
Self::Twelve => 0.009415526,
287-
Self::Thirteen => 0.003559893,
288-
Self::Fourteen => 0.001348575,
289-
Self::Fifteen => 0.000509713,
274+
Self::Zero => 1281.2560107413644,
275+
Self::One => 483.0568390711111,
276+
Self::Two => 182.51295648916735,
277+
Self::Three => 68.97922178775585,
278+
Self::Four => 26.07175968017739,
279+
Self::Five => 9.854090989971207,
280+
Self::Six => 3.7245326671400765,
281+
Self::Seven => 1.4064757626435986,
282+
Self::Eight => 0.5314140100625567,
283+
Self::Nine => 0.20078614761193547,
284+
Self::Ten => 0.07586378286883358,
285+
Self::Eleven => 0.02866389748307224,
286+
Self::Twelve => 0.010830187842605124,
287+
Self::Thirteen => 0.004092010473292413,
288+
Self::Fourteen => 0.001546099657446663,
289+
Self::Fifteen => 0.0005841686296646656,
290290
}
291291
}
292292

@@ -303,22 +303,22 @@ impl Resolution {
303303
#[allow(clippy::inconsistent_digit_grouping)]
304304
pub const fn edge_length_m(self) -> f64 {
305305
match self {
306-
Self::Zero => 1_107_712.591,
307-
Self::One => 418_676.0055,
308-
Self::Two => 158_244.6558,
309-
Self::Three => 59_810.85794,
310-
Self::Four => 22_606.3794,
311-
Self::Five => 8544.408276,
312-
Self::Six => 3229.482772,
313-
Self::Seven => 1220.629759,
314-
Self::Eight => 461.3546837,
315-
Self::Nine => 174.3756681,
316-
Self::Ten => 65.90780749,
317-
Self::Eleven => 24.9105614,
318-
Self::Twelve => 9.415526211,
319-
Self::Thirteen => 3.559893033,
320-
Self::Fourteen => 1.348574562,
321-
Self::Fifteen => 0.509713273,
306+
Self::Zero => 1281256.0107413644,
307+
Self::One => 483056.8390711111,
308+
Self::Two => 182512.95648916735,
309+
Self::Three => 68979.22178775584,
310+
Self::Four => 26071.75968017739,
311+
Self::Five => 9854.090989971206,
312+
Self::Six => 3724.5326671400767,
313+
Self::Seven => 1406.4757626435987,
314+
Self::Eight => 531.4140100625567,
315+
Self::Nine => 200.78614761193546,
316+
Self::Ten => 75.86378286883358,
317+
Self::Eleven => 28.66389748307224,
318+
Self::Twelve => 10.830187842605124,
319+
Self::Thirteen => 4.092010473292413,
320+
Self::Fourteen => 1.546099657446663,
321+
Self::Fifteen => 0.5841686296646657,
322322
}
323323
}
324324

tests/api/avg_edge_len.rs

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use h3o::Resolution;
2+
use std::{
3+
fs::File,
4+
io::{BufRead, BufReader},
5+
path::PathBuf,
6+
};
7+
8+
#[test]
9+
fn golden_file() {
10+
// Load the file generated by tools/average_edge_length
11+
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
12+
path.push("dataset/avgEdgeLen.txt");
13+
14+
let file = File::open(path).expect("open test dataset");
15+
let reader = BufReader::new(file);
16+
let resolutions = Resolution::range(Resolution::Zero, Resolution::Fifteen);
17+
18+
for (resolution, line) in resolutions.zip(reader.lines()) {
19+
let line = line.expect("test input");
20+
let parts = line.split(',').collect::<Vec<&str>>();
21+
let avg_rad = parts[0].parse::<f64>().expect("edge len in radians");
22+
let avg_km = parts[1].parse::<f64>().expect("edge len in kilometers");
23+
let avg_m = parts[2].parse::<f64>().expect("edge len in meters");
24+
25+
assert_eq!(
26+
resolution.edge_length_rads(),
27+
avg_rad,
28+
"avg edge len rad at {resolution}"
29+
);
30+
assert_eq!(
31+
resolution.edge_length_km(),
32+
avg_km,
33+
"avg edge len km at {resolution}"
34+
);
35+
assert_eq!(
36+
resolution.edge_length_m(),
37+
avg_m,
38+
"avg edge len m at {resolution}"
39+
);
40+
}
41+
}

tests/api/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod avg_edge_len;
12
mod base_cell;
23
mod boundary;
34
mod cell_index;

tests/h3/get_hexagon_edge_length_avg_km.rs

-33
This file was deleted.

tests/h3/get_hexagon_edge_length_avg_m.rs

-33
This file was deleted.

tests/h3/get_hexagon_edge_length_avg_rads.rs

-34
This file was deleted.

tests/h3/h3api.rs

-26
Original file line numberDiff line numberDiff line change
@@ -383,32 +383,6 @@ pub fn get_hexagon_area_avg_m2(resolution: Resolution) -> f64 {
383383
out
384384
}
385385

386-
/// Expose `getHexagonEdgeLengthAvgKm`.
387-
pub fn get_hexagon_edge_length_avg_km(resolution: Resolution) -> f64 {
388-
let resolution = u8::from(resolution);
389-
let mut out: f64 = 0.;
390-
unsafe {
391-
let res = h3ron_h3_sys::getHexagonEdgeLengthAvgKm(
392-
resolution.into(),
393-
&mut out,
394-
);
395-
assert_eq!(res, 0, "getHexagonEdgeLengthAvgKm");
396-
}
397-
out
398-
}
399-
400-
/// Expose `getHexagonEdgeLengthAvgM`.
401-
pub fn get_hexagon_edge_length_avg_m(resolution: Resolution) -> f64 {
402-
let resolution = u8::from(resolution);
403-
let mut out: f64 = 0.;
404-
unsafe {
405-
let res =
406-
h3ron_h3_sys::getHexagonEdgeLengthAvgM(resolution.into(), &mut out);
407-
assert_eq!(res, 0, "getHexagonEdgeLengthAvgM");
408-
}
409-
out
410-
}
411-
412386
/// Expose `getIcosahedronFaces`.
413387
pub fn get_icosahedron_faces(index: CellIndex) -> Vec<Face> {
414388
let max_count = max_face_count(index);

tests/h3/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ mod get_directed_edge_origin;
2727
mod get_hexagon_area_avg_km2;
2828
mod get_hexagon_area_avg_m2;
2929
mod get_hexagon_area_avg_rads2;
30-
mod get_hexagon_edge_length_avg_km;
31-
mod get_hexagon_edge_length_avg_m;
32-
mod get_hexagon_edge_length_avg_rads;
3330
mod get_icosahedron_faces;
3431
mod get_num_cells;
3532
mod get_pentagons;

0 commit comments

Comments
 (0)