Skip to main content

chess_corners_core/
ring.rs

1//! Canonical 16-sample rings used by the ChESS detector.
2/// 16 point ring offsets. Order is clockwise starting at top.
3/// This is the FAST-16 pattern scaled to r=5 and rounded,
4/// matching the paper’s "radius 5, 16 samples" design.
5pub const RING5: [(i32, i32); 16] = [
6    (0, -5),
7    (2, -5),
8    (3, -3),
9    (5, -2),
10    (5, 0),
11    (5, 2),
12    (3, 3),
13    (2, 5),
14    (0, 5),
15    (-2, 5),
16    (-3, 3),
17    (-5, 2),
18    (-5, 0),
19    (-5, -2),
20    (-3, -3),
21    (-2, -5),
22];
23
24/// Optional heavier-blur ring (same angles, r=10)
25pub const RING10: [(i32, i32); 16] = [
26    (0, -10),
27    (4, -10),
28    (6, -6),
29    (10, -4),
30    (10, 0),
31    (10, 4),
32    (6, 6),
33    (4, 10),
34    (0, 10),
35    (-4, 10),
36    (-6, 6),
37    (-10, 4),
38    (-10, 0),
39    (-10, -4),
40    (-6, -6),
41    (-4, -10),
42];
43
44/// Valid ring radii and their canonical offset tables.
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
46#[repr(u32)]
47pub enum RingOffsets {
48    /// FAST-16 offsets scaled to r=5.
49    R5 = 5,
50    /// Optional heavier-blur ring with r=10.
51    R10 = 10,
52}
53
54impl RingOffsets {
55    #[inline]
56    pub const fn radius(self) -> u32 {
57        self as u32
58    }
59
60    #[inline]
61    pub const fn offsets(self) -> &'static [(i32, i32); 16] {
62        match self {
63            RingOffsets::R5 => &RING5,
64            RingOffsets::R10 => &RING10,
65        }
66    }
67
68    #[inline]
69    pub const fn from_radius(radius: u32) -> Self {
70        match radius {
71            10 => RingOffsets::R10,
72            _ => RingOffsets::R5,
73        }
74    }
75}
76
77#[inline]
78/// Get the 16-sample ring offsets for the requested radius.
79pub const fn ring_offsets(radius: u32) -> &'static [(i32, i32); 16] {
80    RingOffsets::from_radius(radius).offsets()
81}