use num_traits::Pow;
extern crate nalgebra as na;
use crate::tools::tool::{self, gaussian_likehood};
use na::*;
use nalgebra::base::Vector3;
use nalgebra::{
base::allocator::Allocator, DefaultAllocator, Dim, DimName, DimNameAdd, MatrixMN, RealField,
Scalar,
};
extern crate docify;
use anyhow::{bail, Result};
use nalgebra;
use nalgebra::DimMinimum;
use rand::prelude::*;
use statrs::distribution::{Continuous, Normal};
use statrs::statistics::Distribution;
use std::collections::HashMap;
use std::f64::consts::PI;
use std::ops::Add;
pub struct RansacNormal {
data: Vec<f64>,
round: usize,
in_ratio: f64,
in_thresh: f64,
}
pub fn calc_norm_vector(p1: Vector3<f64>, p2: Vector3<f64>, p3: Vector3<f64>) -> Vector3<f64> {
let v1 = p2 - p1;
let v2 = p3 - p1;
let normal = v1.cross(&v2);
normal / normal.norm()
}
pub fn dis_to_plane(p: Vector3<f64>, normal: Vector3<f64>, origin: Vector3<f64>) -> f64 {
let dot = normal.dot(&p) - normal.dot(&origin);
if dot.abs() < 1e-3 {
return 0.;
}
let dis = dot.abs() / normal.norm();
dis
}
impl RansacNormal {
pub fn rows(&self) -> usize {
self.data.len() / 3
}
pub fn center(&self) -> Vec<f64> {
let pcl = DMatrix::from_row_slice(self.rows(), 3, &self.data);
let x = pcl.column(0);
let y = pcl.column(1);
let z = pcl.column(2);
vec![x.mean(), y.mean(), z.mean()]
}
pub fn ransac_normal(&self, round: usize) -> Result<Vector3<f64>> {
let pcl = DMatrix::from_row_slice(self.rows(), 3, &self.data);
let center = self.center();
let origin = Vector3::new(center[0], center[1], center[2]);
for step in 0..round {
let ids = tool::rand_n_index(self.rows(), 3);
let p1 = Vector3::new(pcl[(ids[0], 0)], pcl[(ids[0], 1)], pcl[(ids[0], 2)]);
let p2 = Vector3::new(pcl[(ids[1], 0)], pcl[(ids[1], 1)], pcl[(ids[1], 2)]);
let p3 = Vector3::new(pcl[(ids[2], 0)], pcl[(ids[2], 1)], pcl[(ids[2], 2)]);
let norm = calc_norm_vector(p1, p2, p3);
let mut n_in = 0;
for index in 0..self.rows() {
let p = Vector3::new(pcl[(index, 0)], pcl[(index, 1)], pcl[(index, 2)]);
let dis = dis_to_plane(p, norm, origin);
if dis < self.in_thresh {
n_in += 1
}
}
let this_ratio = n_in as f64 / self.rows() as f64;
if this_ratio > self.in_ratio {
return Ok(norm);
}
}
bail!("无法找到法线,调整参数")
}
pub fn voxel_grid(&self, voxel_size: f64) -> HashMap<(i32, i32, i32), Vec<Vec<f64>>> {
let mut res: HashMap<(i32, i32, i32), Vec<Vec<f64>>> = HashMap::new();
for i in 0..self.rows() {
let xyz = self.data[i * 3..i * 3 + 3].to_vec();
let ix = (xyz[0] / voxel_size) as i32;
let iy = (xyz[1] / voxel_size) as i32;
let iz = (xyz[2] / voxel_size) as i32;
let index = (ix, iy, iz);
if res.contains_key(&index) {
let mut old: Vec<Vec<f64>> = res[&index].clone();
old.push(xyz);
res.insert(index, old);
} else {
let mut l = Vec::new();
l.push(xyz);
res.insert(index, l);
}
}
res
}
}
#[test]
fn test_normal() {
let pcl = vec![
0.0365432,
0.08029224,
0.12673997,
1.31284406,
0.36646423,
-0.17070852,
1.07315926,
0.27918677,
-0.19051423,
-0.76582586,
0.3525164,
-0.20910616,
-0.01234001,
-0.04495755,
-0.03833314,
-0.15851892,
-0.20942741,
0.1233298,
0.42856567,
0.32450773,
-0.20543443,
0.14900326,
0.23802697,
-0.07059914,
1.95312744,
-0.08339773,
0.24432046,
1.39618658,
-0.60088018,
0.46474034,
];
let pcl = RansacNormal {
data: pcl,
round: 200,
in_ratio: 0.7,
in_thresh: 0.1,
};
let center = pcl.center();
let p1 = Vector3::new(0.0365432, 0.08029224, 0.12673997);
let p2 = Vector3::new(1.31284406, 0.36646423, -0.17070852);
let p3 = Vector3::new(1.07315926, 0.27918677, -0.19051423);
let res = pcl.ransac_normal(200);
dbg!(res);
let res2 = pcl.voxel_grid(1.);
dbg!(res2);
}