Skip to main content

oxihuman_export/
pore_map_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct PoreMap {
6    pub width: u32,
7    pub height: u32,
8    pub pore_mask: Vec<bool>,
9    pub pore_sizes: Vec<f32>,
10}
11
12pub fn new_pore_map(w: u32, h: u32) -> PoreMap {
13    let n = (w * h) as usize;
14    PoreMap {
15        width: w,
16        height: h,
17        pore_mask: vec![false; n],
18        pore_sizes: vec![0.0; n],
19    }
20}
21
22fn idx(m: &PoreMap, x: u32, y: u32) -> usize {
23    (y * m.width + x) as usize
24}
25
26pub fn pore_set(m: &mut PoreMap, x: u32, y: u32, is_pore: bool, size: f32) {
27    let i = idx(m, x, y);
28    m.pore_mask[i] = is_pore;
29    m.pore_sizes[i] = size;
30}
31
32pub fn pore_get(m: &PoreMap, x: u32, y: u32) -> (bool, f32) {
33    let i = idx(m, x, y);
34    (m.pore_mask[i], m.pore_sizes[i])
35}
36
37pub fn pore_count(m: &PoreMap) -> usize {
38    m.pore_mask.iter().filter(|&&b| b).count()
39}
40
41pub fn pore_mean_size(m: &PoreMap) -> f32 {
42    let pores: Vec<f32> = m
43        .pore_mask
44        .iter()
45        .zip(m.pore_sizes.iter())
46        .filter(|(&is_p, _)| is_p)
47        .map(|(_, &s)| s)
48        .collect();
49    if pores.is_empty() {
50        return 0.0;
51    }
52    pores.iter().sum::<f32>() / pores.len() as f32
53}
54
55pub fn pore_density(m: &PoreMap) -> f32 {
56    let total = (m.width * m.height) as usize;
57    if total == 0 {
58        return 0.0;
59    }
60    pore_count(m) as f32 / total as f32
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_new_pore_map() {
69        /* correct size */
70        let m = new_pore_map(4, 4);
71        assert_eq!(m.pore_mask.len(), 16);
72    }
73
74    #[test]
75    fn test_set_get() {
76        /* round-trip */
77        let mut m = new_pore_map(2, 2);
78        pore_set(&mut m, 1, 0, true, 0.5);
79        let (is_p, sz) = pore_get(&m, 1, 0);
80        assert!(is_p);
81        assert!((sz - 0.5).abs() < 1e-6);
82    }
83
84    #[test]
85    fn test_pore_count() {
86        /* count pores */
87        let mut m = new_pore_map(2, 1);
88        pore_set(&mut m, 0, 0, true, 1.0);
89        assert_eq!(pore_count(&m), 1);
90    }
91
92    #[test]
93    fn test_mean_size() {
94        /* mean of two pores */
95        let mut m = new_pore_map(3, 1);
96        pore_set(&mut m, 0, 0, true, 1.0);
97        pore_set(&mut m, 1, 0, true, 3.0);
98        assert!((pore_mean_size(&m) - 2.0).abs() < 1e-6);
99    }
100
101    #[test]
102    fn test_pore_density() {
103        /* half pores */
104        let mut m = new_pore_map(2, 1);
105        pore_set(&mut m, 0, 0, true, 1.0);
106        assert!((pore_density(&m) - 0.5).abs() < 1e-6);
107    }
108
109    #[test]
110    fn test_no_pores() {
111        /* no pores => density 0 */
112        let m = new_pore_map(4, 4);
113        assert!((pore_density(&m)).abs() < 1e-6);
114    }
115}