mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
incomplete port of detector
This commit is contained in:
@@ -401,3 +401,15 @@ impl Default for BitArray {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Vec<u8>> for BitArray {
|
||||
fn into(self) -> Vec<u8> {
|
||||
let mut arr = vec![0; self.get_size()];
|
||||
for x in 0..self.get_size() {
|
||||
if self.get(x) {
|
||||
arr[x] = 1;
|
||||
}
|
||||
}
|
||||
arr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,6 +408,21 @@ impl BitMatrix {
|
||||
rw
|
||||
}
|
||||
|
||||
/// This method returns a column of the bitmatrix.
|
||||
///
|
||||
/// The current implementation may be very slow.
|
||||
pub fn getCol(&self, x: u32) -> BitArray {
|
||||
let mut cw = BitArray::with_size(self.height as usize);
|
||||
|
||||
for y in 0..self.height {
|
||||
if self.get(x, y) {
|
||||
cw.set(y as usize)
|
||||
}
|
||||
}
|
||||
|
||||
cw
|
||||
}
|
||||
|
||||
/**
|
||||
* @param y row to set
|
||||
* @param row {@link BitArray} to copy from
|
||||
@@ -595,6 +610,10 @@ impl BitMatrix {
|
||||
* @return The width of the matrix
|
||||
*/
|
||||
pub fn getWidth(&self) -> u32 {
|
||||
self.width()
|
||||
}
|
||||
|
||||
pub fn width(&self) -> u32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
@@ -602,6 +621,10 @@ impl BitMatrix {
|
||||
* @return The height of the matrix
|
||||
*/
|
||||
pub fn getHeight(&self) -> u32 {
|
||||
self.height()
|
||||
}
|
||||
|
||||
pub fn height(&self) -> u32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
|
||||
@@ -1,182 +1 @@
|
||||
use crate::Point;
|
||||
|
||||
use super::{util::opposite, Direction, Value};
|
||||
|
||||
/**
|
||||
* @brief The BitMatrixCursor represents a current position inside an image and current direction it can advance towards.
|
||||
*
|
||||
* The current position and direction is a PointT<T>. So depending on the type it can be used to traverse the image
|
||||
* in a Bresenham style (PointF) or in a discrete way (step only horizontal/vertical/diagonal (PointI)).
|
||||
*/
|
||||
pub trait BitMatrixCursor {
|
||||
// const BitMatrix* img;
|
||||
|
||||
// POINT p; // current position
|
||||
// POINT d; // current direction
|
||||
|
||||
// BitMatrixCursor(const BitMatrix& image, POINT p, POINT d) : img(&image), p(p) { setDirection(d); }
|
||||
|
||||
fn testAt(&self, p: Point) -> Value; //const
|
||||
// {
|
||||
// return img->isIn(p) ? Value{img->get(p)} : Value{};
|
||||
// }
|
||||
|
||||
fn blackAt(&self, pos: Point) -> bool {
|
||||
self.testAt(pos).isBlack()
|
||||
}
|
||||
fn whiteAt(&self, pos: Point) -> bool {
|
||||
self.testAt(pos).isWhite()
|
||||
}
|
||||
|
||||
fn isIn(&self, p: Point) -> bool; // { return img->isIn(p); }
|
||||
fn isInSelf(&self) -> bool; // { return self.isIn(p); }
|
||||
fn isBlack(&self) -> bool; // { return blackAt(p); }
|
||||
fn isWhite(&self) -> bool; // { return whiteAt(p); }
|
||||
|
||||
fn front(&self) -> &Point; //{ return d; }
|
||||
fn back(&self) -> Point; // { return {-d.x, -d.y}; }
|
||||
fn left(&self) -> Point; //{ return {d.y, -d.x}; }
|
||||
fn right(&self) -> Point; //{ return {-d.y, d.x}; }
|
||||
fn direction(&self, dir: Direction) -> Point {
|
||||
self.right() * Into::<i32>::into(dir)
|
||||
}
|
||||
|
||||
fn turnBack(&mut self); // noexcept { d = back(); }
|
||||
fn turnLeft(&mut self); //noexcept { d = left(); }
|
||||
fn turnRight(&mut self); //noexcept { d = right(); }
|
||||
fn turn(&mut self, dir: Direction); //noexcept { d = direction(dir); }
|
||||
|
||||
fn edgeAt_point(&self, d: Point) -> Value;
|
||||
// {
|
||||
// Value v = testAt(p);
|
||||
// return testAt(p + d) != v ? v : Value();
|
||||
// }
|
||||
|
||||
fn edgeAtFront(&self) -> Value {
|
||||
return self.edgeAt_point(*self.front());
|
||||
}
|
||||
fn edgeAtBack(&self) -> Value {
|
||||
self.edgeAt_point(self.back())
|
||||
}
|
||||
fn edgeAtLeft(&self) -> Value {
|
||||
self.edgeAt_point(self.left())
|
||||
}
|
||||
fn edgeAtRight(&self) -> Value {
|
||||
self.edgeAt_point(self.right())
|
||||
}
|
||||
fn edgeAt_direction(&self, dir: Direction) -> Value {
|
||||
self.edgeAt_point(self.direction(dir))
|
||||
}
|
||||
|
||||
fn setDirection(&mut self, dir: Point); // { d = bresenhamDirection(dir); }
|
||||
// fn setDirection(&self, dir: Point);// { d = dir; }
|
||||
|
||||
fn step(&mut self, s: Option<f32>) -> bool; // DEF to 1
|
||||
// {
|
||||
// p += s * d;
|
||||
// return isIn(p);
|
||||
// }
|
||||
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: Point) -> Self;
|
||||
fn turnedBack(&self) -> Self; // { return {*img, p, back()}; }
|
||||
// {
|
||||
// auto res = *this;
|
||||
// res.p += d;
|
||||
// return res;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief stepToEdge advances cursor to one step behind the next (or n-th) edge.
|
||||
* @param nth number of edges to pass
|
||||
* @param range max number of steps to take
|
||||
* @param backup whether or not to backup one step so we land in front of the edge
|
||||
* @return number of steps taken or 0 if moved outside of range/image
|
||||
*/
|
||||
fn stepToEdge(&mut self, nth: Option<i32>, range: Option<i32>, backup: Option<bool>) -> i32;
|
||||
// fn stepToEdge(&self, int nth = 1, int range = 0, bool backup = false) -> i32
|
||||
// {
|
||||
// // TODO: provide an alternative and faster out-of-bounds check than isIn() inside testAt()
|
||||
// int steps = 0;
|
||||
// auto lv = testAt(p);
|
||||
|
||||
// while (nth && (!range || steps < range) && lv.isValid()) {
|
||||
// ++steps;
|
||||
// auto v = testAt(p + steps * d);
|
||||
// if (lv != v) {
|
||||
// lv = v;
|
||||
// --nth;
|
||||
// }
|
||||
// }
|
||||
// if (backup)
|
||||
// --steps;
|
||||
// p += steps * d;
|
||||
// return steps * (nth == 0);
|
||||
// }
|
||||
|
||||
fn stepAlongEdge(&mut self, dir: Direction, skipCorner: Option<bool>) -> bool
|
||||
// fn stepAlongEdge(&self, dir:Direction, skipCorner:Option<bool> = false) -> bool
|
||||
{
|
||||
let skipCorner = if let Some(sc) = skipCorner { sc } else { false };
|
||||
|
||||
if !self.edgeAt_direction(dir).isValid() {
|
||||
self.turn(dir);
|
||||
} else if self.edgeAtFront().isValid() {
|
||||
self.turn(opposite(dir));
|
||||
if self.edgeAtFront().isValid() {
|
||||
self.turn(opposite(dir));
|
||||
if self.edgeAtFront().isValid() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut ret = self.step(None);
|
||||
|
||||
if ret && skipCorner && !self.edgeAt_direction(dir).isValid() {
|
||||
self.turn(dir);
|
||||
ret = self.step(None);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn countEdges(&mut self, range: i32) -> i32 {
|
||||
let mut res = 0;
|
||||
let mut range = range;
|
||||
|
||||
let mut steps;
|
||||
|
||||
while {
|
||||
steps = if range == 0 {
|
||||
0
|
||||
} else {
|
||||
self.stepToEdge(Some(1), Some(range), None)
|
||||
};
|
||||
steps > 0
|
||||
} {
|
||||
range -= steps;
|
||||
res += 1;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn p(&self) -> Point;
|
||||
|
||||
// template<typename ARRAY>
|
||||
// ARRAY readPattern(int range = 0)
|
||||
// {
|
||||
// ARRAY res;
|
||||
// for (auto& i : res)
|
||||
// i = stepToEdge(1, range);
|
||||
// return res;
|
||||
// }
|
||||
|
||||
// template<typename ARRAY>
|
||||
// ARRAY readPatternFromBlack(int maxWhitePrefix, int range = 0)
|
||||
// {
|
||||
// if (maxWhitePrefix && isWhite() && !stepToEdge(1, maxWhitePrefix))
|
||||
// return {};
|
||||
// return readPattern<ARRAY>(range);
|
||||
// }
|
||||
}
|
||||
|
||||
184
src/common/cpp_essentials/bitmatrix_cursor_trait.rs
Normal file
184
src/common/cpp_essentials/bitmatrix_cursor_trait.rs
Normal file
@@ -0,0 +1,184 @@
|
||||
use crate::Point;
|
||||
|
||||
use super::{util::opposite, Direction, Value};
|
||||
|
||||
/**
|
||||
* @brief The BitMatrixCursor represents a current position inside an image and current direction it can advance towards.
|
||||
*
|
||||
* The current position and direction is a PointT<T>. So depending on the type it can be used to traverse the image
|
||||
* in a Bresenham style (PointF) or in a discrete way (step only horizontal/vertical/diagonal (PointI)).
|
||||
*/
|
||||
pub trait BitMatrixCursorTrait {
|
||||
// const BitMatrix* img;
|
||||
|
||||
// POINT p; // current position
|
||||
// POINT d; // current direction
|
||||
|
||||
// BitMatrixCursor(const BitMatrix& image, POINT p, POINT d) : img(&image), p(p) { setDirection(d); }
|
||||
|
||||
fn testAt(&self, p: Point) -> Value; //const
|
||||
// {
|
||||
// return img->isIn(p) ? Value{img->get(p)} : Value{};
|
||||
// }
|
||||
|
||||
fn blackAt(&self, pos: Point) -> bool {
|
||||
self.testAt(pos).isBlack()
|
||||
}
|
||||
fn whiteAt(&self, pos: Point) -> bool {
|
||||
self.testAt(pos).isWhite()
|
||||
}
|
||||
|
||||
fn isIn(&self, p: Point) -> bool; // { return img->isIn(p); }
|
||||
fn isInSelf(&self) -> bool; // { return self.isIn(p); }
|
||||
fn isBlack(&self) -> bool; // { return blackAt(p); }
|
||||
fn isWhite(&self) -> bool; // { return whiteAt(p); }
|
||||
|
||||
fn front(&self) -> &Point; //{ return d; }
|
||||
fn back(&self) -> Point; // { return {-d.x, -d.y}; }
|
||||
fn left(&self) -> Point; //{ return {d.y, -d.x}; }
|
||||
fn right(&self) -> Point; //{ return {-d.y, d.x}; }
|
||||
fn direction(&self, dir: Direction) -> Point {
|
||||
self.right() * Into::<i32>::into(dir)
|
||||
}
|
||||
|
||||
fn turnBack(&mut self); // noexcept { d = back(); }
|
||||
fn turnLeft(&mut self); //noexcept { d = left(); }
|
||||
fn turnRight(&mut self); //noexcept { d = right(); }
|
||||
fn turn(&mut self, dir: Direction); //noexcept { d = direction(dir); }
|
||||
|
||||
fn edgeAt_point(&self, d: Point) -> Value;
|
||||
// {
|
||||
// Value v = testAt(p);
|
||||
// return testAt(p + d) != v ? v : Value();
|
||||
// }
|
||||
|
||||
fn edgeAtFront(&self) -> Value {
|
||||
return self.edgeAt_point(*self.front());
|
||||
}
|
||||
fn edgeAtBack(&self) -> Value {
|
||||
self.edgeAt_point(self.back())
|
||||
}
|
||||
fn edgeAtLeft(&self) -> Value {
|
||||
self.edgeAt_point(self.left())
|
||||
}
|
||||
fn edgeAtRight(&self) -> Value {
|
||||
self.edgeAt_point(self.right())
|
||||
}
|
||||
fn edgeAt_direction(&self, dir: Direction) -> Value {
|
||||
self.edgeAt_point(self.direction(dir))
|
||||
}
|
||||
|
||||
fn setDirection(&mut self, dir: Point); // { d = bresenhamDirection(dir); }
|
||||
// fn setDirection(&self, dir: Point);// { d = dir; }
|
||||
|
||||
fn step(&mut self, s: Option<f32>) -> bool; // DEF to 1
|
||||
// {
|
||||
// p += s * d;
|
||||
// return isIn(p);
|
||||
// }
|
||||
|
||||
fn movedBy<T: BitMatrixCursorTrait>(self, d: Point) -> Self;
|
||||
fn turnedBack(&self) -> Self; // { return {*img, p, back()}; }
|
||||
// {
|
||||
// auto res = *this;
|
||||
// res.p += d;
|
||||
// return res;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief stepToEdge advances cursor to one step behind the next (or n-th) edge.
|
||||
* @param nth number of edges to pass
|
||||
* @param range max number of steps to take
|
||||
* @param backup whether or not to backup one step so we land in front of the edge
|
||||
* @return number of steps taken or 0 if moved outside of range/image
|
||||
*/
|
||||
fn stepToEdge(&mut self, nth: Option<i32>, range: Option<i32>, backup: Option<bool>) -> i32;
|
||||
// fn stepToEdge(&self, int nth = 1, int range = 0, bool backup = false) -> i32
|
||||
// {
|
||||
// // TODO: provide an alternative and faster out-of-bounds check than isIn() inside testAt()
|
||||
// int steps = 0;
|
||||
// auto lv = testAt(p);
|
||||
|
||||
// while (nth && (!range || steps < range) && lv.isValid()) {
|
||||
// ++steps;
|
||||
// auto v = testAt(p + steps * d);
|
||||
// if (lv != v) {
|
||||
// lv = v;
|
||||
// --nth;
|
||||
// }
|
||||
// }
|
||||
// if (backup)
|
||||
// --steps;
|
||||
// p += steps * d;
|
||||
// return steps * (nth == 0);
|
||||
// }
|
||||
|
||||
fn stepAlongEdge(&mut self, dir: Direction, skipCorner: Option<bool>) -> bool
|
||||
// fn stepAlongEdge(&self, dir:Direction, skipCorner:Option<bool> = false) -> bool
|
||||
{
|
||||
let skipCorner = if let Some(sc) = skipCorner { sc } else { false };
|
||||
|
||||
if !self.edgeAt_direction(dir).isValid() {
|
||||
self.turn(dir);
|
||||
} else if self.edgeAtFront().isValid() {
|
||||
self.turn(opposite(dir));
|
||||
if self.edgeAtFront().isValid() {
|
||||
self.turn(opposite(dir));
|
||||
if self.edgeAtFront().isValid() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut ret = self.step(None);
|
||||
|
||||
if ret && skipCorner && !self.edgeAt_direction(dir).isValid() {
|
||||
self.turn(dir);
|
||||
ret = self.step(None);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn countEdges(&mut self, range: i32) -> i32 {
|
||||
let mut res = 0;
|
||||
let mut range = range;
|
||||
|
||||
let mut steps;
|
||||
|
||||
while {
|
||||
steps = if range == 0 {
|
||||
0
|
||||
} else {
|
||||
self.stepToEdge(Some(1), Some(range), None)
|
||||
};
|
||||
steps > 0
|
||||
} {
|
||||
range -= steps;
|
||||
res += 1;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn p(&self) -> Point;
|
||||
|
||||
fn d(&self) -> Point;
|
||||
|
||||
// template<typename ARRAY>
|
||||
// ARRAY readPattern(int range = 0)
|
||||
// {
|
||||
// ARRAY res;
|
||||
// for (auto& i : res)
|
||||
// i = stepToEdge(1, range);
|
||||
// return res;
|
||||
// }
|
||||
|
||||
// template<typename ARRAY>
|
||||
// ARRAY readPatternFromBlack(int maxWhitePrefix, int range = 0)
|
||||
// {
|
||||
// if (maxWhitePrefix && isWhite() && !stepToEdge(1, maxWhitePrefix))
|
||||
// return {};
|
||||
// return readPattern<ARRAY>(range);
|
||||
// }
|
||||
}
|
||||
@@ -9,8 +9,8 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
BitMatrixCursor, EdgeTracer, FastEdgeToEdgeCounter, Pattern, RegressionLine,
|
||||
RegressionLineTrait,
|
||||
BitMatrixCursorTrait, EdgeTracer, FastEdgeToEdgeCounter, Pattern, RegressionLine,
|
||||
RegressionLineTrait, UpdateMinMax, UpdateMinMaxFloat,
|
||||
};
|
||||
|
||||
pub fn CenterFromEnd<const N: usize, T: Into<f32> + std::iter::Sum<T> + Copy>(
|
||||
@@ -41,7 +41,7 @@ pub fn CenterFromEnd<const N: usize, T: Into<f32> + std::iter::Sum<T> + Copy>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ReadSymmetricPattern<const N: usize, Cursor: BitMatrixCursor>(
|
||||
pub fn ReadSymmetricPattern<const N: usize, Cursor: BitMatrixCursorTrait>(
|
||||
cur: &mut Cursor,
|
||||
range: i32,
|
||||
) -> Option<Pattern<N>> {
|
||||
@@ -82,7 +82,7 @@ pub fn CheckSymmetricPattern<
|
||||
const RELAXED_THRESHOLD: bool,
|
||||
const LEN: usize,
|
||||
const SUM: usize,
|
||||
T: BitMatrixCursor,
|
||||
T: BitMatrixCursorTrait,
|
||||
>(
|
||||
cur: &mut T,
|
||||
pattern: &Pattern<LEN>,
|
||||
@@ -143,7 +143,7 @@ pub fn CheckSymmetricPattern<
|
||||
res.into_iter().sum::<PatternType>() as i32
|
||||
}
|
||||
|
||||
pub fn AverageEdgePixels<T: BitMatrixCursor>(
|
||||
pub fn AverageEdgePixels<T: BitMatrixCursorTrait>(
|
||||
cur: &mut T,
|
||||
range: i32,
|
||||
numOfEdges: u32,
|
||||
@@ -481,17 +481,42 @@ pub fn FindConcentricPatternCorners(
|
||||
Some(res)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub struct ConcentricPattern {
|
||||
p: Point,
|
||||
size: i32,
|
||||
pub p: Point,
|
||||
pub size: i32,
|
||||
}
|
||||
|
||||
impl std::ops::Sub for ConcentricPattern {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
let new_p = self.p - rhs.p;
|
||||
Self {
|
||||
p: new_p,
|
||||
size: self.size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConcentricPattern {
|
||||
pub fn dot(self, other: ConcentricPattern) -> f32 {
|
||||
Point::dot(self.p, other.p)
|
||||
}
|
||||
|
||||
pub fn cross(self, other: ConcentricPattern) -> f32 {
|
||||
Point::cross(self.p, other.p)
|
||||
}
|
||||
|
||||
pub fn distance(self, other: ConcentricPattern) -> f32 {
|
||||
Point::distance(self.p, other.p)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn LocateConcentricPattern<
|
||||
const RELAXED_THRESHOLD: bool,
|
||||
const LEN: usize,
|
||||
const SUM: usize,
|
||||
T: BitMatrixCursor,
|
||||
>(
|
||||
image: &BitMatrix,
|
||||
pattern: &Pattern<LEN>,
|
||||
@@ -540,13 +565,3 @@ pub fn LocateConcentricPattern<
|
||||
size: (maxSpread + minSpread) / 2,
|
||||
})
|
||||
}
|
||||
|
||||
fn UpdateMinMax<T: Ord + Copy>(min: &mut T, max: &mut T, val: T) {
|
||||
*min = std::cmp::min(*min, val);
|
||||
*max = std::cmp::max(*max, val);
|
||||
}
|
||||
|
||||
fn UpdateMinMaxFloat(min: &mut f64, max: &mut f64, val: f64) {
|
||||
*min = f64::min(*min, val);
|
||||
*max = f64::max(*max, val);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::{BitMatrixCursor, Direction, RegressionLineTrait, StepResult, Value};
|
||||
use super::{BitMatrixCursorTrait, Direction, RegressionLineTrait, StepResult, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EdgeTracer<'a> {
|
||||
@@ -34,7 +34,7 @@ pub struct EdgeTracer<'a> {
|
||||
// }
|
||||
// }
|
||||
|
||||
impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
impl BitMatrixCursorTrait for EdgeTracer<'_> {
|
||||
fn testAt(&self, p: Point) -> Value {
|
||||
if self.img.isIn(p, 0) {
|
||||
Value::from(self.img.get_point(p))
|
||||
@@ -119,7 +119,7 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
self.isIn(self.p)
|
||||
}
|
||||
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: Point) -> Self {
|
||||
fn movedBy<T: BitMatrixCursorTrait>(self, d: Point) -> Self {
|
||||
let mut res = self;
|
||||
res.p += d;
|
||||
|
||||
@@ -166,6 +166,10 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
fn p(&self) -> Point {
|
||||
self.p
|
||||
}
|
||||
|
||||
fn d(&self) -> Point {
|
||||
self.d
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EdgeTracer<'_> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::BitMatrixCursor;
|
||||
use super::BitMatrixCursorTrait;
|
||||
|
||||
pub struct FastEdgeToEdgeCounter {
|
||||
// const uint8_t* p = nullptr;
|
||||
@@ -7,7 +7,7 @@ pub struct FastEdgeToEdgeCounter {
|
||||
}
|
||||
|
||||
impl FastEdgeToEdgeCounter {
|
||||
pub fn new<T: BitMatrixCursor>(_cur: &T) -> Self {
|
||||
pub fn new<T: BitMatrixCursorTrait>(_cur: &T) -> Self {
|
||||
todo!()
|
||||
// stride = cur.d.y * cur.img->width() + cur.d.x;
|
||||
// p = cur.img->row(cur.p.y).begin() + cur.p.x;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod bitmatrix_cursor;
|
||||
pub mod bitmatrix_cursor_trait;
|
||||
pub mod concentric_finder;
|
||||
pub mod direction;
|
||||
pub mod dm_regression_line;
|
||||
@@ -12,6 +13,7 @@ pub mod util;
|
||||
pub mod value;
|
||||
|
||||
pub use bitmatrix_cursor::*;
|
||||
pub use bitmatrix_cursor_trait::*;
|
||||
pub use concentric_finder::*;
|
||||
pub use direction::*;
|
||||
pub use dm_regression_line::*;
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{common::Result, Exceptions};
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
Exceptions,
|
||||
};
|
||||
|
||||
pub type PatternType = u16;
|
||||
pub type Pattern<const N: usize> = [PatternType; N];
|
||||
@@ -337,8 +340,16 @@ pub struct FixedPattern<const N: usize, const SUM: usize, const IS_SPARCE: bool
|
||||
data: [PatternType; N],
|
||||
}
|
||||
|
||||
impl<const N: usize, const SUM: usize, const IS_SPARCE: bool> Into<Pattern<N>>
|
||||
for FixedPattern<N, SUM, IS_SPARCE>
|
||||
{
|
||||
fn into(self) -> Pattern<N> {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, const SUM: usize, const IS_SPARCE: bool> FixedPattern<N, SUM, IS_SPARCE> {
|
||||
pub fn new(data: [PatternType; N]) -> Self {
|
||||
pub const fn new(data: [PatternType; N]) -> Self {
|
||||
FixedPattern { data }
|
||||
}
|
||||
|
||||
@@ -546,7 +557,15 @@ impl<T: Into<PatternType>> From<T> for Color {
|
||||
}
|
||||
}
|
||||
|
||||
fn GetPatternRow<T: Into<PatternType> + Copy + Default + From<T>>(
|
||||
pub fn GetPatternRowTP(matrix: &BitMatrix, r: u32, pr: &mut PatternRow, transpose: bool) {
|
||||
if (transpose) {
|
||||
GetPatternRow(&Into::<Vec<u8>>::into(matrix.getCol(r)), pr)
|
||||
} else {
|
||||
GetPatternRow(&Into::<Vec<u8>>::into(matrix.getRow(r)), pr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn GetPatternRow<T: Into<PatternType> + Copy + Default + From<T>>(
|
||||
b_row: &[T],
|
||||
p_row: &mut PatternRow,
|
||||
) {
|
||||
@@ -655,7 +674,9 @@ mod tests {
|
||||
fn basic_pattern_view() {
|
||||
let mut p_row = PatternRow::default();
|
||||
GetPatternRow(
|
||||
&[0_u16, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1],
|
||||
&[
|
||||
0_u16, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
|
||||
],
|
||||
&mut p_row,
|
||||
);
|
||||
|
||||
|
||||
@@ -26,3 +26,15 @@ pub fn opposite(dir: Direction) -> Direction {
|
||||
Direction::Left
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn UpdateMinMax<T: Ord + Copy>(min: &mut T, max: &mut T, val: T) {
|
||||
*min = std::cmp::min(*min, val);
|
||||
*max = std::cmp::max(*max, val);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn UpdateMinMaxFloat(min: &mut f64, max: &mut f64, val: f64) {
|
||||
*min = f64::min(*min, val);
|
||||
*max = f64::max(*max, val);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user