mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
remove indirection for RxingResultPoint
Previously, the struct was passed around everywhere as a reference. It only holds two floats, so there's no real need for indirection. Now it's being passed as a value.
This commit is contained in:
@@ -94,10 +94,10 @@ impl<'a> Detector<'_> {
|
||||
// 4. Sample the grid
|
||||
let bits = self.sample_grid(
|
||||
self.image,
|
||||
&bulls_eye_corners[self.shift as usize % 4],
|
||||
&bulls_eye_corners[(self.shift as usize + 1) % 4],
|
||||
&bulls_eye_corners[(self.shift as usize + 2) % 4],
|
||||
&bulls_eye_corners[(self.shift as usize + 3) % 4],
|
||||
bulls_eye_corners[self.shift as usize % 4],
|
||||
bulls_eye_corners[(self.shift as usize + 1) % 4],
|
||||
bulls_eye_corners[(self.shift as usize + 2) % 4],
|
||||
bulls_eye_corners[(self.shift as usize + 3) % 4],
|
||||
)?;
|
||||
|
||||
// 5. Get the corners of the matrix.
|
||||
@@ -122,10 +122,10 @@ impl<'a> Detector<'_> {
|
||||
&mut self,
|
||||
bulls_eye_corners: &[RXingResultPoint],
|
||||
) -> Result<(), Exceptions> {
|
||||
if !self.is_valid(&bulls_eye_corners[0])
|
||||
|| !self.is_valid(&bulls_eye_corners[1])
|
||||
|| !self.is_valid(&bulls_eye_corners[2])
|
||||
|| !self.is_valid(&bulls_eye_corners[3])
|
||||
if !self.is_valid(bulls_eye_corners[0])
|
||||
|| !self.is_valid(bulls_eye_corners[1])
|
||||
|| !self.is_valid(bulls_eye_corners[2])
|
||||
|| !self.is_valid(bulls_eye_corners[3])
|
||||
{
|
||||
return Err(Exceptions::NotFoundException(Some(
|
||||
"no valid points".to_owned(),
|
||||
@@ -134,10 +134,10 @@ impl<'a> Detector<'_> {
|
||||
let length = 2 * self.nb_center_layers;
|
||||
// Get the bits around the bull's eye
|
||||
let sides = [
|
||||
self.sample_line(&bulls_eye_corners[0], &bulls_eye_corners[1], length), // Right side
|
||||
self.sample_line(&bulls_eye_corners[1], &bulls_eye_corners[2], length), // Bottom
|
||||
self.sample_line(&bulls_eye_corners[2], &bulls_eye_corners[3], length), // Left side
|
||||
self.sample_line(&bulls_eye_corners[3], &bulls_eye_corners[0], length), // Top
|
||||
self.sample_line(bulls_eye_corners[0], bulls_eye_corners[1], length), // Right side
|
||||
self.sample_line(bulls_eye_corners[1], bulls_eye_corners[2], length), // Bottom
|
||||
self.sample_line(bulls_eye_corners[2], bulls_eye_corners[3], length), // Left side
|
||||
self.sample_line(bulls_eye_corners[3], bulls_eye_corners[0], length), // Top
|
||||
];
|
||||
|
||||
// bullsEyeCorners[shift] is the corner of the bulls'eye that has three
|
||||
@@ -500,10 +500,10 @@ impl<'a> Detector<'_> {
|
||||
fn sample_grid(
|
||||
&self,
|
||||
image: &BitMatrix,
|
||||
top_left: &RXingResultPoint,
|
||||
top_right: &RXingResultPoint,
|
||||
bottom_right: &RXingResultPoint,
|
||||
bottom_left: &RXingResultPoint,
|
||||
top_left: RXingResultPoint,
|
||||
top_right: RXingResultPoint,
|
||||
bottom_right: RXingResultPoint,
|
||||
bottom_left: RXingResultPoint,
|
||||
) -> Result<BitMatrix, Exceptions> {
|
||||
let sampler = DefaultGridSampler::default();
|
||||
let dimension = self.get_dimension();
|
||||
@@ -542,7 +542,7 @@ impl<'a> Detector<'_> {
|
||||
* @param size number of bits
|
||||
* @return the array of bits as an int (first bit is high-order bit of result)
|
||||
*/
|
||||
fn sample_line(&self, p1: &RXingResultPoint, p2: &RXingResultPoint, size: u32) -> u32 {
|
||||
fn sample_line(&self, p1: RXingResultPoint, p2: RXingResultPoint, size: u32) -> u32 {
|
||||
let mut result = 0;
|
||||
|
||||
let d = Self::distance(p1, p2);
|
||||
@@ -724,7 +724,7 @@ impl<'a> Detector<'_> {
|
||||
x >= 0 && x < self.image.getWidth() as i32 && y >= 0 && y < self.image.getHeight() as i32
|
||||
}
|
||||
|
||||
fn is_valid(&self, point: &RXingResultPoint) -> bool {
|
||||
fn is_valid(&self, point: RXingResultPoint) -> bool {
|
||||
let x = MathUtils::round(point.getX());
|
||||
let y = MathUtils::round(point.getY());
|
||||
self.is_valid_points(x, y)
|
||||
@@ -734,7 +734,7 @@ impl<'a> Detector<'_> {
|
||||
MathUtils::distance(a.get_x(), a.get_y(), b.get_x(), b.get_y())
|
||||
}
|
||||
|
||||
fn distance(a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
fn distance(a: RXingResultPoint, b: RXingResultPoint) -> f32 {
|
||||
MathUtils::distance(a.getX(), a.getY(), b.getX(), b.getY())
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ impl BitMatrix {
|
||||
((self.bits[offset] >> (x & 0x1f)) & 1) != 0
|
||||
}
|
||||
|
||||
pub fn get_point(&self, point: &RXingResultPoint) -> bool {
|
||||
pub fn get_point(&self, point: RXingResultPoint) -> bool {
|
||||
self.get(point.x as u32, point.y as u32)
|
||||
// let offset = self.get_offset(point.y as u32, point.x as u32);
|
||||
// ((self.bits[offset] >> (x & 0x1f)) & 1) != 0
|
||||
@@ -700,7 +700,7 @@ impl BitMatrix {
|
||||
new_bm
|
||||
}
|
||||
|
||||
pub fn isIn(&self, p: &RXingResultPoint, b: i32) -> bool {
|
||||
pub fn isIn(&self, p: RXingResultPoint, b: i32) -> bool {
|
||||
b as f32 <= p.x
|
||||
&& p.x < self.getWidth() as f32 - b as f32
|
||||
&& b as f32 <= p.y
|
||||
|
||||
@@ -280,7 +280,7 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
Ok(self.center_edges(&y.unwrap(), &z.unwrap(), &x.unwrap(), &t.unwrap()))
|
||||
Ok(self.center_edges(y.unwrap(), z.unwrap(), x.unwrap(), t.unwrap()))
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
}
|
||||
@@ -322,10 +322,10 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
*/
|
||||
fn center_edges(
|
||||
&self,
|
||||
y: &RXingResultPoint,
|
||||
z: &RXingResultPoint,
|
||||
x: &RXingResultPoint,
|
||||
t: &RXingResultPoint,
|
||||
y: RXingResultPoint,
|
||||
z: RXingResultPoint,
|
||||
x: RXingResultPoint,
|
||||
t: RXingResultPoint,
|
||||
) -> [RXingResultPoint; 4] {
|
||||
//
|
||||
// t t
|
||||
|
||||
@@ -68,8 +68,8 @@ impl<'a> Detector<'_> {
|
||||
let bottomRight = points[2];
|
||||
let topRight = points[3];
|
||||
|
||||
let mut dimensionTop = self.transitionsBetween(&topLeft, &topRight) + 1;
|
||||
let mut dimensionRight = self.transitionsBetween(&bottomRight, &topRight) + 1;
|
||||
let mut dimensionTop = self.transitionsBetween(topLeft, topRight) + 1;
|
||||
let mut dimensionRight = self.transitionsBetween(bottomRight, topRight) + 1;
|
||||
if (dimensionTop & 0x01) == 1 {
|
||||
dimensionTop += 1;
|
||||
}
|
||||
@@ -85,10 +85,10 @@ impl<'a> Detector<'_> {
|
||||
|
||||
let bits = Self::sampleGrid(
|
||||
self.image,
|
||||
&topLeft,
|
||||
&bottomLeft,
|
||||
&bottomRight,
|
||||
&topRight,
|
||||
topLeft,
|
||||
bottomLeft,
|
||||
bottomRight,
|
||||
topRight,
|
||||
dimensionTop,
|
||||
dimensionRight,
|
||||
)?;
|
||||
@@ -135,10 +135,10 @@ impl<'a> Detector<'_> {
|
||||
let pointC = cornerPoints[3];
|
||||
let pointD = cornerPoints[2];
|
||||
|
||||
let trAB = self.transitionsBetween(&pointA, &pointB);
|
||||
let trBC = self.transitionsBetween(&pointB, &pointC);
|
||||
let trCD = self.transitionsBetween(&pointC, &pointD);
|
||||
let trDA = self.transitionsBetween(&pointD, &pointA);
|
||||
let trAB = self.transitionsBetween(pointA, pointB);
|
||||
let trBC = self.transitionsBetween(pointB, pointC);
|
||||
let trCD = self.transitionsBetween(pointC, pointD);
|
||||
let trDA = self.transitionsBetween(pointD, pointA);
|
||||
|
||||
// 0..3
|
||||
// : :
|
||||
@@ -183,11 +183,11 @@ impl<'a> Detector<'_> {
|
||||
|
||||
// Transition detection on the edge is not stable.
|
||||
// To safely detect, shift the points to the module center.
|
||||
let tr = self.transitionsBetween(&pointA, &pointD);
|
||||
let tr = self.transitionsBetween(pointA, pointD);
|
||||
let pointBs = Self::shiftPoint(pointB, pointC, (tr + 1) * 4);
|
||||
let pointCs = Self::shiftPoint(pointC, pointB, (tr + 1) * 4);
|
||||
let trBA = self.transitionsBetween(&pointBs, &pointA);
|
||||
let trCD = self.transitionsBetween(&pointCs, &pointD);
|
||||
let trBA = self.transitionsBetween(pointBs, pointA);
|
||||
let trCD = self.transitionsBetween(pointCs, pointD);
|
||||
|
||||
// 0..3
|
||||
// | :
|
||||
@@ -222,13 +222,13 @@ impl<'a> Detector<'_> {
|
||||
let pointD = points[3];
|
||||
|
||||
// shift points for safe transition detection.
|
||||
let mut trTop = self.transitionsBetween(&pointA, &pointD);
|
||||
let mut trRight = self.transitionsBetween(&pointB, &pointD);
|
||||
let mut trTop = self.transitionsBetween(pointA, pointD);
|
||||
let mut trRight = self.transitionsBetween(pointB, pointD);
|
||||
let pointAs = Self::shiftPoint(pointA, pointB, (trRight + 1) * 4);
|
||||
let pointCs = Self::shiftPoint(pointC, pointB, (trTop + 1) * 4);
|
||||
|
||||
trTop = self.transitionsBetween(&pointAs, &pointD);
|
||||
trRight = self.transitionsBetween(&pointCs, &pointD);
|
||||
trTop = self.transitionsBetween(pointAs, pointD);
|
||||
trRight = self.transitionsBetween(pointCs, pointD);
|
||||
|
||||
let candidate1 = RXingResultPoint::new(
|
||||
pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop as f32 + 1.0),
|
||||
@@ -239,20 +239,20 @@ impl<'a> Detector<'_> {
|
||||
pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight as f32 + 1.0),
|
||||
);
|
||||
|
||||
if !self.isValid(&candidate1) {
|
||||
if self.isValid(&candidate2) {
|
||||
if !self.isValid(candidate1) {
|
||||
if self.isValid(candidate2) {
|
||||
return Some(candidate2);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
if !self.isValid(&candidate2) {
|
||||
if !self.isValid(candidate2) {
|
||||
return Some(candidate1);
|
||||
}
|
||||
|
||||
let sumc1 = self.transitionsBetween(&pointAs, &candidate1)
|
||||
+ self.transitionsBetween(&pointCs, &candidate1);
|
||||
let sumc2 = self.transitionsBetween(&pointAs, &candidate2)
|
||||
+ self.transitionsBetween(&pointCs, &candidate2);
|
||||
let sumc1 = self.transitionsBetween(pointAs, candidate1)
|
||||
+ self.transitionsBetween(pointCs, candidate1);
|
||||
let sumc2 = self.transitionsBetween(pointAs, candidate2)
|
||||
+ self.transitionsBetween(pointCs, candidate2);
|
||||
|
||||
if sumc1 > sumc2 {
|
||||
Some(candidate1)
|
||||
@@ -274,16 +274,16 @@ impl<'a> Detector<'_> {
|
||||
let mut pointD = points[3];
|
||||
|
||||
// calculate pseudo dimensions
|
||||
let mut dimH = self.transitionsBetween(&pointA, &pointD) + 1;
|
||||
let mut dimV = self.transitionsBetween(&pointC, &pointD) + 1;
|
||||
let mut dimH = self.transitionsBetween(pointA, pointD) + 1;
|
||||
let mut dimV = self.transitionsBetween(pointC, pointD) + 1;
|
||||
|
||||
// shift points for safe dimension detection
|
||||
let mut pointAs = Self::shiftPoint(pointA, pointB, dimV * 4);
|
||||
let mut pointCs = Self::shiftPoint(pointC, pointB, dimH * 4);
|
||||
|
||||
// calculate more precise dimensions
|
||||
dimH = self.transitionsBetween(&pointAs, &pointD) + 1;
|
||||
dimV = self.transitionsBetween(&pointCs, &pointD) + 1;
|
||||
dimH = self.transitionsBetween(pointAs, pointD) + 1;
|
||||
dimV = self.transitionsBetween(pointCs, pointD) + 1;
|
||||
if (dimH & 0x01) == 1 {
|
||||
dimH += 1;
|
||||
}
|
||||
@@ -316,7 +316,7 @@ impl<'a> Detector<'_> {
|
||||
[pointAs, pointBs, pointCs, pointDs]
|
||||
}
|
||||
|
||||
fn isValid(&self, p: &RXingResultPoint) -> bool {
|
||||
fn isValid(&self, p: RXingResultPoint) -> bool {
|
||||
p.getX() >= 0.0
|
||||
&& p.getX() <= self.image.getWidth() as f32 - 1.0
|
||||
&& p.getY() > 0.0
|
||||
@@ -325,10 +325,10 @@ impl<'a> Detector<'_> {
|
||||
|
||||
fn sampleGrid(
|
||||
image: &BitMatrix,
|
||||
topLeft: &RXingResultPoint,
|
||||
bottomLeft: &RXingResultPoint,
|
||||
bottomRight: &RXingResultPoint,
|
||||
topRight: &RXingResultPoint,
|
||||
topLeft: RXingResultPoint,
|
||||
bottomLeft: RXingResultPoint,
|
||||
bottomRight: RXingResultPoint,
|
||||
topRight: RXingResultPoint,
|
||||
dimensionX: u32,
|
||||
dimensionY: u32,
|
||||
) -> Result<BitMatrix, Exceptions> {
|
||||
@@ -360,7 +360,7 @@ impl<'a> Detector<'_> {
|
||||
/**
|
||||
* Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.
|
||||
*/
|
||||
fn transitionsBetween(&self, from: &RXingResultPoint, to: &RXingResultPoint) -> u32 {
|
||||
fn transitionsBetween(&self, from: RXingResultPoint, to: RXingResultPoint) -> u32 {
|
||||
// See QR Code Detector, sizeOfBlackWhiteBlackRun()
|
||||
let mut fromX = from.getX().floor() as i32;
|
||||
let mut fromY = from.getY().floor() as i32;
|
||||
|
||||
@@ -16,19 +16,19 @@ pub trait BitMatrixCursor {
|
||||
|
||||
// BitMatrixCursor(const BitMatrix& image, POINT p, POINT d) : img(&image), p(p) { setDirection(d); }
|
||||
|
||||
fn testAt(&self, p: &RXingResultPoint) -> Value; //const
|
||||
// {
|
||||
// return img->isIn(p) ? Value{img->get(p)} : Value{};
|
||||
// }
|
||||
fn testAt(&self, p: RXingResultPoint) -> Value; //const
|
||||
// {
|
||||
// return img->isIn(p) ? Value{img->get(p)} : Value{};
|
||||
// }
|
||||
|
||||
fn blackAt(&self, pos: &RXingResultPoint) -> bool {
|
||||
fn blackAt(&self, pos: RXingResultPoint) -> bool {
|
||||
self.testAt(pos).isBlack()
|
||||
}
|
||||
fn whiteAt(&self, pos: &RXingResultPoint) -> bool {
|
||||
fn whiteAt(&self, pos: RXingResultPoint) -> bool {
|
||||
self.testAt(pos).isWhite()
|
||||
}
|
||||
|
||||
fn isIn(&self, p: &RXingResultPoint) -> bool; // { return img->isIn(p); }
|
||||
fn isIn(&self, p: RXingResultPoint) -> 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); }
|
||||
@@ -46,30 +46,30 @@ pub trait BitMatrixCursor {
|
||||
fn turnRight(&mut self); //noexcept { d = right(); }
|
||||
fn turn(&mut self, dir: Direction); //noexcept { d = direction(dir); }
|
||||
|
||||
fn edgeAt_point(&self, d: &RXingResultPoint) -> Value;
|
||||
fn edgeAt_point(&self, d: RXingResultPoint) -> Value;
|
||||
// {
|
||||
// Value v = testAt(p);
|
||||
// return testAt(p + d) != v ? v : Value();
|
||||
// }
|
||||
|
||||
fn edgeAtFront(&self) -> Value {
|
||||
return self.edgeAt_point(self.front());
|
||||
return self.edgeAt_point(*self.front());
|
||||
}
|
||||
fn edgeAtBack(&self) -> Value {
|
||||
self.edgeAt_point(&self.back())
|
||||
self.edgeAt_point(self.back())
|
||||
}
|
||||
fn edgeAtLeft(&self) -> Value {
|
||||
self.edgeAt_point(&self.left())
|
||||
self.edgeAt_point(self.left())
|
||||
}
|
||||
fn edgeAtRight(&self) -> Value {
|
||||
self.edgeAt_point(&self.right())
|
||||
self.edgeAt_point(self.right())
|
||||
}
|
||||
fn edgeAt_direction(&self, dir: Direction) -> Value {
|
||||
self.edgeAt_point(&self.direction(dir))
|
||||
self.edgeAt_point(self.direction(dir))
|
||||
}
|
||||
|
||||
fn setDirection(&mut self, dir: &RXingResultPoint); // { d = bresenhamDirection(dir); }
|
||||
// fn setDirection(&self, dir:&RXingResultPoint);// { d = dir; }
|
||||
fn setDirection(&mut self, dir: RXingResultPoint); // { d = bresenhamDirection(dir); }
|
||||
// fn setDirection(&self, dir: RXingResultPoint);// { d = dir; }
|
||||
|
||||
fn step(&mut self, s: Option<f32>) -> bool; // DEF to 1
|
||||
// {
|
||||
@@ -77,7 +77,7 @@ pub trait BitMatrixCursor {
|
||||
// return isIn(p);
|
||||
// }
|
||||
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: &RXingResultPoint) -> Self;
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: RXingResultPoint) -> Self;
|
||||
// {
|
||||
// auto res = *this;
|
||||
// res.p += d;
|
||||
|
||||
@@ -76,7 +76,7 @@ fn Scan(
|
||||
// follow left leg upwards
|
||||
t.turnRight();
|
||||
t.state = 1;
|
||||
CHECK!(t.traceLine(&t.right(), lineL)?);
|
||||
CHECK!(t.traceLine(t.right(), lineL)?);
|
||||
CHECK!(t.traceCorner(&mut t.right(), &mut tl)?);
|
||||
lineL.reverse();
|
||||
let mut tlTracer = t;
|
||||
@@ -84,19 +84,19 @@ fn Scan(
|
||||
// follow left leg downwards
|
||||
t = startTracer.clone();
|
||||
t.state = 1;
|
||||
t.setDirection(&tlTracer.right());
|
||||
CHECK!(t.traceLine(&t.left(), lineL)?);
|
||||
t.setDirection(tlTracer.right());
|
||||
CHECK!(t.traceLine(t.left(), lineL)?);
|
||||
if !lineL.isValid() {
|
||||
t.updateDirectionFromOrigin(&tl);
|
||||
t.updateDirectionFromOrigin(tl);
|
||||
}
|
||||
let up = t.back();
|
||||
CHECK!(t.traceCorner(&mut t.left(), &mut bl)?);
|
||||
|
||||
// follow bottom leg right
|
||||
t.state = 2;
|
||||
CHECK!(t.traceLine(&t.left(), lineB)?);
|
||||
CHECK!(t.traceLine(t.left(), lineB)?);
|
||||
if !lineB.isValid() {
|
||||
t.updateDirectionFromOrigin(&bl);
|
||||
t.updateDirectionFromOrigin(bl);
|
||||
}
|
||||
let right = *t.front();
|
||||
CHECK!(t.traceCorner(&mut t.left(), &mut br)?);
|
||||
@@ -109,9 +109,9 @@ fn Scan(
|
||||
|
||||
// at this point we found a plausible L-shape and are now looking for the b/w pattern at the top and right:
|
||||
// follow top row right 'half way' (4 gaps), see traceGaps break condition with 'invalid' line
|
||||
tlTracer.setDirection(&right);
|
||||
tlTracer.setDirection(right);
|
||||
CHECK!(tlTracer.traceGaps(
|
||||
&tlTracer.right(),
|
||||
tlTracer.right(),
|
||||
lineT,
|
||||
maxStepSize,
|
||||
&mut DMRegressionLine::default()
|
||||
@@ -124,9 +124,9 @@ fn Scan(
|
||||
maxStepSize = std::cmp::min(lineT.length() as i32 / 3, (lenL / 5.0) as i32) * 2;
|
||||
|
||||
// follow up until we reach the top line
|
||||
t.setDirection(&up);
|
||||
t.setDirection(up);
|
||||
t.state = 3;
|
||||
CHECK!(t.traceGaps(&t.left(), lineR, maxStepSize, lineT)?);
|
||||
CHECK!(t.traceGaps(t.left(), lineR, maxStepSize, lineT)?);
|
||||
CHECK!(t.traceCorner(&mut t.left(), &mut tr)?);
|
||||
|
||||
let lenT = distance(&tl, &tr) - 1.0;
|
||||
@@ -140,7 +140,7 @@ fn Scan(
|
||||
);
|
||||
|
||||
// continue top row right until we cross the right line
|
||||
CHECK!(tlTracer.traceGaps(&tlTracer.right(), lineT, maxStepSize, lineR)?);
|
||||
CHECK!(tlTracer.traceGaps(tlTracer.right(), lineT, maxStepSize, lineR)?);
|
||||
|
||||
// #ifdef PRINT_DEBUG
|
||||
// printf("L: %.1f, %.1f ^ %.1f, %.1f > %.1f, %.1f (%d : %d : %d : %d)\n", bl.x, bl.y,
|
||||
@@ -173,8 +173,8 @@ fn Scan(
|
||||
f64::INFINITY
|
||||
};
|
||||
};
|
||||
splitDouble(lineT.modules(&tl, &tr)?, &mut dimT, &mut fracT);
|
||||
splitDouble(lineR.modules(&br, &tr)?, &mut dimR, &mut fracR);
|
||||
splitDouble(lineT.modules(tl, tr)?, &mut dimT, &mut fracT);
|
||||
splitDouble(lineR.modules(br, tr)?, &mut dimR, &mut fracR);
|
||||
|
||||
// #ifdef PRINT_DEBUG
|
||||
// printf("L: %.1f, %.1f ^ %.1f, %.1f > %.1f, %.1f ^> %.1f, %.1f\n", bl.x, bl.y,
|
||||
@@ -197,24 +197,24 @@ fn Scan(
|
||||
|
||||
CHECK!((10..=144).contains(&dimT) && (8..=144).contains(&dimR));
|
||||
|
||||
let movedTowardsBy = |a: &RXingResultPoint,
|
||||
b1: &RXingResultPoint,
|
||||
b2: &RXingResultPoint,
|
||||
let movedTowardsBy = |a: RXingResultPoint,
|
||||
b1: RXingResultPoint,
|
||||
b2: RXingResultPoint,
|
||||
d: f32|
|
||||
-> RXingResultPoint {
|
||||
*a + d * RXingResultPoint::normalized(
|
||||
RXingResultPoint::normalized(*b1 - *a) + RXingResultPoint::normalized(*b2 - *a),
|
||||
a + d * RXingResultPoint::normalized(
|
||||
RXingResultPoint::normalized(b1 - a) + RXingResultPoint::normalized(b2 - a),
|
||||
)
|
||||
};
|
||||
|
||||
// shrink shape by half a pixel to go from center of white pixel outside of code to the edge between white and black
|
||||
let sourcePoints = Quadrilateral::with_points(
|
||||
movedTowardsBy(&tl, &tr, &bl, 0.5),
|
||||
movedTowardsBy(tl, tr, bl, 0.5),
|
||||
// move the tr point a little less because the jagged top and right line tend to be statistically slightly
|
||||
// inclined toward the center anyway.
|
||||
movedTowardsBy(&tr, &br, &tl, 0.3),
|
||||
movedTowardsBy(&br, &bl, &tr, 0.5),
|
||||
movedTowardsBy(&bl, &tl, &br, 0.5),
|
||||
movedTowardsBy(tr, br, tl, 0.3),
|
||||
movedTowardsBy(br, bl, tr, 0.5),
|
||||
movedTowardsBy(bl, tl, br, 0.5),
|
||||
);
|
||||
|
||||
let grid_sampler = DefaultGridSampler::default();
|
||||
@@ -303,7 +303,7 @@ pub fn detect(
|
||||
y: (image.getHeight() / 2) as f32,
|
||||
}; //PointF(image.width() / 2, image.height() / 2);
|
||||
let startPos =
|
||||
RXingResultPoint::centered(&(center - center * dir + MIN_SYMBOL_SIZE as i32 / 2 * dir));
|
||||
RXingResultPoint::centered(center - center * dir + MIN_SYMBOL_SIZE as i32 / 2 * dir);
|
||||
|
||||
if let Some(history) = &mut history {
|
||||
history.borrow_mut().clear(0);
|
||||
|
||||
@@ -58,11 +58,11 @@ impl RegressionLine for DMRegressionLine {
|
||||
}
|
||||
}
|
||||
|
||||
fn signedDistance(&self, p: &RXingResultPoint) -> f32 {
|
||||
RXingResultPoint::dot(self.normal(), *p) - self.c
|
||||
fn signedDistance(&self, p: RXingResultPoint) -> f32 {
|
||||
RXingResultPoint::dot(self.normal(), p) - self.c
|
||||
}
|
||||
|
||||
fn distance_single(&self, p: &RXingResultPoint) -> f32 {
|
||||
fn distance_single(&self, p: RXingResultPoint) -> f32 {
|
||||
(self.signedDistance(p)).abs()
|
||||
}
|
||||
|
||||
@@ -74,13 +74,13 @@ impl RegressionLine for DMRegressionLine {
|
||||
self.c = f32::NAN;
|
||||
}
|
||||
|
||||
fn add(&mut self, p: &RXingResultPoint) -> Result<(), Exceptions> {
|
||||
fn add(&mut self, p: RXingResultPoint) -> Result<(), Exceptions> {
|
||||
if self.direction_inward == RXingResultPoint::default() {
|
||||
return Err(Exceptions::IllegalStateException(None));
|
||||
}
|
||||
self.points.push(*p);
|
||||
self.points.push(p);
|
||||
if self.points.len() == 1 {
|
||||
self.c = RXingResultPoint::dot(self.normal(), *p);
|
||||
self.c = RXingResultPoint::dot(self.normal(), p);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -89,8 +89,8 @@ impl RegressionLine for DMRegressionLine {
|
||||
self.points.pop();
|
||||
}
|
||||
|
||||
fn setDirectionInward(&mut self, d: &RXingResultPoint) {
|
||||
self.direction_inward = RXingResultPoint::normalized(*d);
|
||||
fn setDirectionInward(&mut self, d: RXingResultPoint) {
|
||||
self.direction_inward = RXingResultPoint::normalized(d);
|
||||
}
|
||||
|
||||
fn evaluate_max_distance(
|
||||
@@ -112,7 +112,7 @@ impl RegressionLine for DMRegressionLine {
|
||||
// return sd > maxSignedDist || sd < -2 * maxSignedDist;
|
||||
// });
|
||||
// points.erase(end, points.end());
|
||||
points.retain(|p| {
|
||||
points.retain(|&p| {
|
||||
let sd = self.signedDistance(p) as f64;
|
||||
!(sd > maxSignedDist || sd < -2.0 * maxSignedDist)
|
||||
});
|
||||
@@ -142,8 +142,8 @@ impl RegressionLine for DMRegressionLine {
|
||||
max.y = float_max(max.y, p.y);
|
||||
}
|
||||
let diff = max - min;
|
||||
let len = RXingResultPoint::maxAbsComponent(&diff);
|
||||
let steps = float_min((diff.x).abs(), (diff.y).abs());
|
||||
let len = diff.maxAbsComponent();
|
||||
let steps = float_min(diff.x.abs(), diff.y.abs());
|
||||
// due to aliasing we get bad extrapolations if the line is short and too close to vertical/horizontal
|
||||
steps > 2.0 || len > 50.0
|
||||
}
|
||||
@@ -237,8 +237,8 @@ impl DMRegressionLine {
|
||||
|
||||
pub fn modules(
|
||||
&mut self,
|
||||
beg: &RXingResultPoint,
|
||||
end: &RXingResultPoint,
|
||||
beg: RXingResultPoint,
|
||||
end: RXingResultPoint,
|
||||
) -> Result<f64, Exceptions> {
|
||||
if self.points.len() <= 3 {
|
||||
return Err(Exceptions::IllegalStateException(None));
|
||||
@@ -257,26 +257,27 @@ impl DMRegressionLine {
|
||||
for i in 1..self.points.len() {
|
||||
// for (size_t i = 1; i < _points.size(); ++i)
|
||||
gapSizes.push(self.distance(
|
||||
&self.project(&self.points[i]),
|
||||
&self.project(&self.points[i - 1]),
|
||||
self.project(self.points[i]),
|
||||
self.project(self.points[i - 1]),
|
||||
) as f64);
|
||||
}
|
||||
|
||||
// calculate the (expected average) distance of two adjacent pixels
|
||||
let unitPixelDist = RXingResultPoint::length(RXingResultPoint::bresenhamDirection(
|
||||
&(*self
|
||||
.points
|
||||
self.points
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
- *self
|
||||
- self
|
||||
.points
|
||||
.first()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
|
||||
.copied()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
)) as f64;
|
||||
|
||||
// calculate the width of 2 modules (first black pixel to first black pixel)
|
||||
let mut sumFront: f64 =
|
||||
self.distance(beg, &self.project(&self.points[0])) as f64 - unitPixelDist;
|
||||
self.distance(beg, self.project(self.points[0])) as f64 - unitPixelDist;
|
||||
let mut sumBack: f64 = 0.0; // (last black pixel to last black pixel)
|
||||
for dist in gapSizes {
|
||||
// for (auto dist : gapSizes) {
|
||||
@@ -294,9 +295,10 @@ impl DMRegressionLine {
|
||||
sumFront
|
||||
+ self.distance(
|
||||
end,
|
||||
&self.project(
|
||||
self.project(
|
||||
self.points
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
),
|
||||
) as f64,
|
||||
|
||||
@@ -31,7 +31,7 @@ pub struct EdgeTracer<'a> {
|
||||
// }
|
||||
|
||||
impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
fn testAt(&self, p: &RXingResultPoint) -> Value {
|
||||
fn testAt(&self, p: RXingResultPoint) -> Value {
|
||||
if self.img.isIn(p, 0) {
|
||||
Value::from(self.img.get_point(p))
|
||||
} else {
|
||||
@@ -39,20 +39,20 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn isIn(&self, p: &RXingResultPoint) -> bool {
|
||||
fn isIn(&self, p: RXingResultPoint) -> bool {
|
||||
self.img.isIn(p, 0)
|
||||
}
|
||||
|
||||
fn isInSelf(&self) -> bool {
|
||||
self.isIn(&self.p)
|
||||
self.isIn(self.p)
|
||||
}
|
||||
|
||||
fn isBlack(&self) -> bool {
|
||||
self.blackAt(&self.p)
|
||||
self.blackAt(self.p)
|
||||
}
|
||||
|
||||
fn isWhite(&self) -> bool {
|
||||
self.whiteAt(&self.p)
|
||||
self.whiteAt(self.p)
|
||||
}
|
||||
|
||||
fn front(&self) -> &RXingResultPoint {
|
||||
@@ -96,28 +96,28 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
self.d = self.direction(dir)
|
||||
}
|
||||
|
||||
fn edgeAt_point(&self, d: &RXingResultPoint) -> Value {
|
||||
let v = self.testAt(&self.p);
|
||||
if self.testAt(&(self.p + *d)) != v {
|
||||
fn edgeAt_point(&self, d: RXingResultPoint) -> Value {
|
||||
let v = self.testAt(self.p);
|
||||
if self.testAt(self.p + d) != v {
|
||||
v
|
||||
} else {
|
||||
Value::Invalid
|
||||
}
|
||||
}
|
||||
|
||||
fn setDirection(&mut self, dir: &RXingResultPoint) {
|
||||
self.d = RXingResultPoint::bresenhamDirection(dir)
|
||||
fn setDirection(&mut self, dir: RXingResultPoint) {
|
||||
self.d = dir.bresenhamDirection();
|
||||
}
|
||||
|
||||
fn step(&mut self, s: Option<f32>) -> bool {
|
||||
let s = if let Some(s) = s { s } else { 1.0 };
|
||||
self.p += self.d * s;
|
||||
self.isIn(&self.p)
|
||||
self.isIn(self.p)
|
||||
}
|
||||
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: &RXingResultPoint) -> Self {
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: RXingResultPoint) -> Self {
|
||||
let mut res = self;
|
||||
res.p += *d;
|
||||
res.p += d;
|
||||
|
||||
res
|
||||
}
|
||||
@@ -135,11 +135,11 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
let backup = if let Some(b) = backup { b } else { false };
|
||||
// TODO: provide an alternative and faster out-of-bounds check than isIn() inside testAt()
|
||||
let mut steps = 0;
|
||||
let mut lv = self.testAt(&self.p);
|
||||
let mut lv = self.testAt(self.p);
|
||||
|
||||
while nth > 0 && (range <= 0 || steps < range) && lv.isValid() {
|
||||
steps += 1;
|
||||
let v = self.testAt(&(self.p + steps * self.d));
|
||||
let v = self.testAt(self.p + steps * self.d);
|
||||
if lv != v {
|
||||
lv = v;
|
||||
nth -= 1;
|
||||
@@ -167,11 +167,11 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
fn traceStep(
|
||||
&mut self,
|
||||
dEdge: &RXingResultPoint,
|
||||
dEdge: RXingResultPoint,
|
||||
maxStepSize: i32,
|
||||
goodDirection: bool,
|
||||
) -> Result<StepResult, Exceptions> {
|
||||
let dEdge = RXingResultPoint::mainDirection(*dEdge);
|
||||
let dEdge = RXingResultPoint::mainDirection(dEdge);
|
||||
for breadth in 1..=(if maxStepSize == 1 {
|
||||
2
|
||||
} else if goodDirection {
|
||||
@@ -189,19 +189,19 @@ impl<'a> EdgeTracer<'_> {
|
||||
+ (if i & 1 > 0 { (i + 1) / 2 } else { -i / 2 }) * dEdge;
|
||||
// dbg!(pEdge);
|
||||
|
||||
if !self.blackAt(&(pEdge + dEdge)) {
|
||||
if !self.blackAt(pEdge + dEdge) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// found black pixel -> go 'outward' until we hit the b/w border
|
||||
for _j in 0..(std::cmp::max(maxStepSize, 3)) {
|
||||
// for (int j = 0; j < std::max(maxStepSize, 3) && isIn(pEdge); ++j) {
|
||||
if self.whiteAt(&pEdge) {
|
||||
if self.whiteAt(pEdge) {
|
||||
// if we are not making any progress, we still have another endless loop bug
|
||||
if self.p == RXingResultPoint::centered(&pEdge) {
|
||||
if self.p == pEdge.centered() {
|
||||
return Err(Exceptions::IllegalStateException(None));
|
||||
}
|
||||
self.p = RXingResultPoint::centered(&pEdge);
|
||||
self.p = pEdge.centered();
|
||||
|
||||
// if (self.history && maxStepSize == 1) {
|
||||
if let Some(history) = &self.history {
|
||||
@@ -222,12 +222,12 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(StepResult::Found);
|
||||
}
|
||||
pEdge = pEdge - dEdge;
|
||||
if self.blackAt(&(pEdge - self.d)) {
|
||||
if self.blackAt(pEdge - self.d) {
|
||||
pEdge = pEdge - self.d;
|
||||
}
|
||||
// dbg!(pEdge);
|
||||
|
||||
if !self.isIn(&pEdge) {
|
||||
if !self.isIn(pEdge) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -239,9 +239,9 @@ impl<'a> EdgeTracer<'_> {
|
||||
Ok(StepResult::OpenEnd)
|
||||
}
|
||||
|
||||
pub fn updateDirectionFromOrigin(&mut self, origin: &RXingResultPoint) -> bool {
|
||||
pub fn updateDirectionFromOrigin(&mut self, origin: RXingResultPoint) -> bool {
|
||||
let old_d = self.d;
|
||||
self.setDirection(&(self.p - origin));
|
||||
self.setDirection(self.p - origin);
|
||||
// if the new direction is pointing "backward", i.e. angle(new, old) > 90 deg -> break
|
||||
if RXingResultPoint::dot(self.d, old_d) < 0.0 {
|
||||
return false;
|
||||
@@ -260,24 +260,24 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
pub fn traceLine<T: RegressionLine>(
|
||||
&mut self,
|
||||
dEdge: &RXingResultPoint,
|
||||
dEdge: RXingResultPoint,
|
||||
line: &mut T,
|
||||
) -> Result<bool, Exceptions> {
|
||||
line.setDirectionInward(dEdge);
|
||||
loop {
|
||||
// log(self.p);
|
||||
line.add(&self.p)?;
|
||||
line.add(self.p)?;
|
||||
if line.points().len() % 50 == 10 {
|
||||
if !line.evaluate_max_distance(None, None) {
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.updateDirectionFromOrigin(
|
||||
&(self.p - line.project(&self.p)
|
||||
self.p - line.project(self.p)
|
||||
+ **line
|
||||
.points()
|
||||
.first()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
) {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -291,7 +291,7 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
pub fn traceGaps<T: RegressionLine>(
|
||||
&mut self,
|
||||
dEdge: &RXingResultPoint,
|
||||
dEdge: RXingResultPoint,
|
||||
line: &mut T,
|
||||
maxStepSize: i32,
|
||||
finishLine: &mut T,
|
||||
@@ -325,14 +325,14 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
// if we drifted too far outside of the code, break
|
||||
if line.isValid()
|
||||
&& line.signedDistance(&self.p) < -5.0
|
||||
&& (!line.evaluate_max_distance(None, None) || line.signedDistance(&self.p) < -5.0)
|
||||
&& line.signedDistance(self.p) < -5.0
|
||||
&& (!line.evaluate_max_distance(None, None) || line.signedDistance(self.p) < -5.0)
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// if we are drifting towards the inside of the code, pull the current position back out onto the line
|
||||
if line.isValid() && line.signedDistance(&self.p) > 3.0 {
|
||||
if line.isValid() && line.signedDistance(self.p) > 3.0 {
|
||||
// The current direction d and the line we are tracing are supposed to be roughly parallel.
|
||||
// In case the 'go outward' step in traceStep lead us astray, we might end up with a line
|
||||
// that is almost perpendicular to d. Then the back-projection below can result in an
|
||||
@@ -350,7 +350,7 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let mut np = line.project(&self.p);
|
||||
let mut np = line.project(self.p);
|
||||
// make sure we are making progress even when back-projecting:
|
||||
// consider a 90deg corner, rotated 45deg. we step away perpendicular from the line and get
|
||||
// back projected where we left off the line.
|
||||
@@ -362,14 +362,14 @@ impl<'a> EdgeTracer<'_> {
|
||||
line.project(
|
||||
line.points()
|
||||
.last()
|
||||
.as_ref()
|
||||
.copied()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
),
|
||||
) < 1.0
|
||||
{
|
||||
np += self.d;
|
||||
}
|
||||
self.p = RXingResultPoint::centered(&np);
|
||||
self.p = RXingResultPoint::centered(np);
|
||||
} else {
|
||||
let stepLengthInMainDir = if line.points().is_empty() {
|
||||
0.0
|
||||
@@ -380,10 +380,11 @@ impl<'a> EdgeTracer<'_> {
|
||||
- line
|
||||
.points()
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
)
|
||||
};
|
||||
line.add(&self.p)?;
|
||||
line.add(self.p)?;
|
||||
|
||||
if stepLengthInMainDir > 1.0 {
|
||||
gaps += 1;
|
||||
@@ -392,11 +393,12 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.updateDirectionFromOrigin(
|
||||
&(self.p - line.project(&self.p)
|
||||
+ *line
|
||||
self.p - line.project(self.p)
|
||||
+ line
|
||||
.points()
|
||||
.first()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
|
||||
.copied()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
) {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -418,7 +420,7 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
if finishLine.isValid() {
|
||||
maxStepSize =
|
||||
std::cmp::min(maxStepSize, (finishLine.signedDistance(&self.p)) as i32);
|
||||
std::cmp::min(maxStepSize, (finishLine.signedDistance(self.p)) as i32);
|
||||
}
|
||||
|
||||
let stepResult = self.traceStep(dEdge, maxStepSize, line.isValid())?;
|
||||
@@ -428,7 +430,7 @@ impl<'a> EdgeTracer<'_> {
|
||||
{
|
||||
return Ok(stepResult == StepResult::OpenEnd
|
||||
&& finishLine.isValid()
|
||||
&& (finishLine.signedDistance(&self.p)) as i32 <= maxStepSize + 1);
|
||||
&& (finishLine.signedDistance(self.p)) as i32 <= maxStepSize + 1);
|
||||
}
|
||||
} //while (true);
|
||||
}
|
||||
@@ -442,10 +444,10 @@ impl<'a> EdgeTracer<'_> {
|
||||
// log(p);
|
||||
*corner = self.p;
|
||||
std::mem::swap(&mut self.d, dir);
|
||||
self.traceStep(&(-1.0 * dir), 2, false)?;
|
||||
self.traceStep(-1.0 * (*dir), 2, false)?;
|
||||
// #ifdef PRINT_DEBUG
|
||||
// printf("turn: %.0f x %.0f -> %.2f, %.2f\n", p.x, p.y, d.x, d.y);
|
||||
// #endif
|
||||
Ok(self.isIn(corner) && self.isIn(&self.p))
|
||||
Ok(self.isIn(*corner) && self.isIn(self.p))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ pub fn IsConvex(poly: &Quadrilateral) -> bool {
|
||||
{
|
||||
let d1 = poly.0[(i + 2) % N] - poly.0[(i + 1) % N];
|
||||
let d2 = poly.0[i] - poly.0[(i + 1) % N];
|
||||
let cp = RXingResultPoint::cross(&d1, &d2);
|
||||
let cp = d1.cross(d2);
|
||||
|
||||
m = if m.abs() > cp { cp } else { m.abs() };
|
||||
|
||||
@@ -186,14 +186,14 @@ pub fn RotatedCorners(q: &Quadrilateral, n: Option<i32>, mirror: Option<bool>) -
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn IsInside(p: &RXingResultPoint, q: &Quadrilateral) -> bool {
|
||||
pub fn IsInside(p: RXingResultPoint, q: &Quadrilateral) -> bool {
|
||||
// Test if p is on the same side (right or left) of all polygon segments
|
||||
let mut pos = 0;
|
||||
let mut neg = 0;
|
||||
for i in 0..q.0.len()
|
||||
// for (int i = 0; i < Size(q); ++i)
|
||||
{
|
||||
if RXingResultPoint::cross(&(*p - q.0[i]), &(q.0[(i + 1) % q.0.len()] - q.0[i])) < 0.0 {
|
||||
if RXingResultPoint::cross(p - q.0[i], q.0[(i + 1) % q.0.len()] - q.0[i]) < 0.0 {
|
||||
neg += 1;
|
||||
} else {
|
||||
pos += 1;
|
||||
|
||||
@@ -13,7 +13,7 @@ pub trait RegressionLine {
|
||||
// fn intersect<T: RegressionLine, T2: RegressionLine>(&self, l1: &T, l2: &T2)
|
||||
// -> RXingResultPoint;
|
||||
|
||||
// fn evaluate_begin_end(&self, begin:&RXingResultPoint, end:&RXingResultPoint) -> bool;// {
|
||||
// fn evaluate_begin_end(&self, begin: RXingResultPoint, end: RXingResultPoint) -> bool;// {
|
||||
// {
|
||||
// let mean = std::accumulate(begin, end, PointF()) / std::distance(begin, end);
|
||||
// PointF::value_t sumXX = 0, sumYY = 0, sumXY = 0;
|
||||
@@ -43,8 +43,8 @@ pub trait RegressionLine {
|
||||
fn evaluate(&mut self, points: &[RXingResultPoint]) -> bool; // { return self.evaluate_begin_end(&points.front(), &points.back() + 1); }
|
||||
fn evaluateSelf(&mut self) -> bool;
|
||||
|
||||
fn distance(&self, a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
crate::result_point_utils::distance(a, b)
|
||||
fn distance(&self, a: RXingResultPoint, b: RXingResultPoint) -> f32 {
|
||||
crate::result_point_utils::distance(&a, &b)
|
||||
}
|
||||
|
||||
// RegressionLine() { _points.reserve(16); } // arbitrary but plausible start size (tiny performance improvement)
|
||||
@@ -63,10 +63,10 @@ pub trait RegressionLine {
|
||||
fn length(&self) -> u32; //const { return _points.size() >= 2 ? int(distance(_points.front(), _points.back())) : 0; }
|
||||
fn isValid(&self) -> bool; //const { return !std::isnan(a); }
|
||||
fn normal(&self) -> RXingResultPoint; //const { return isValid() ? PointF(a, b) : _directionInward; }
|
||||
fn signedDistance(&self, p: &RXingResultPoint) -> f32; //const { return dot(normal(), p) - c; }
|
||||
fn distance_single(&self, p: &RXingResultPoint) -> f32; //const { return std::abs(signedDistance(PointF(p))); }
|
||||
fn project(&self, p: &RXingResultPoint) -> RXingResultPoint {
|
||||
*p - self.normal() * self.signedDistance(p)
|
||||
fn signedDistance(&self, p: RXingResultPoint) -> f32; //const { return dot(normal(), p) - c; }
|
||||
fn distance_single(&self, p: RXingResultPoint) -> f32; //const { return std::abs(signedDistance(PointF(p))); }
|
||||
fn project(&self, p: RXingResultPoint) -> RXingResultPoint {
|
||||
p - self.normal() * self.signedDistance(p)
|
||||
}
|
||||
|
||||
fn reset(&mut self);
|
||||
@@ -76,16 +76,16 @@ pub trait RegressionLine {
|
||||
// a = b = c = NAN;
|
||||
// }
|
||||
|
||||
fn add(&mut self, p: &RXingResultPoint) -> Result<(), Exceptions>; //{
|
||||
// assert(_directionInward != PointF());
|
||||
// _points.push_back(p);
|
||||
// if (_points.size() == 1)
|
||||
// c = dot(normal(), p);
|
||||
// }
|
||||
fn add(&mut self, p: RXingResultPoint) -> Result<(), Exceptions>; //{
|
||||
// assert(_directionInward != PointF());
|
||||
// _points.push_back(p);
|
||||
// if (_points.size() == 1)
|
||||
// c = dot(normal(), p);
|
||||
// }
|
||||
|
||||
fn pop_back(&mut self); // { _points.pop_back(); }
|
||||
|
||||
fn setDirectionInward(&mut self, d: &RXingResultPoint); //{ _directionInward = normalized(d); }
|
||||
fn setDirectionInward(&mut self, d: RXingResultPoint); //{ _directionInward = normalized(d); }
|
||||
|
||||
// fn evaluate(&self, double maxSignedDist = -1, bool updatePoints = false) -> bool
|
||||
fn evaluate_max_distance(
|
||||
|
||||
@@ -68,7 +68,7 @@ pub fn decode(
|
||||
leftRowIndicatorColumn = Some(getRowIndicatorColumn(
|
||||
image,
|
||||
boundingBox.clone(),
|
||||
imageTopLeft.as_ref().unwrap(),
|
||||
imageTopLeft.unwrap(),
|
||||
true,
|
||||
minCodewordWidth,
|
||||
maxCodewordWidth,
|
||||
@@ -78,7 +78,7 @@ pub fn decode(
|
||||
rightRowIndicatorColumn = Some(getRowIndicatorColumn(
|
||||
image,
|
||||
boundingBox.clone(),
|
||||
imageTopRight.as_ref().unwrap(),
|
||||
imageTopRight.unwrap(),
|
||||
false,
|
||||
minCodewordWidth,
|
||||
maxCodewordWidth,
|
||||
@@ -358,7 +358,7 @@ fn getBarcodeMetadata<T: DetectionRXingResultRowIndicatorColumn>(
|
||||
fn getRowIndicatorColumn<'a>(
|
||||
image: &BitMatrix,
|
||||
boundingBox: Rc<BoundingBox>,
|
||||
startPoint: &RXingResultPoint,
|
||||
startPoint: RXingResultPoint,
|
||||
leftToRight: bool,
|
||||
minCodewordWidth: u32,
|
||||
maxCodewordWidth: u32,
|
||||
|
||||
@@ -18,22 +18,26 @@ pub struct RXingResultPoint {
|
||||
pub(crate) x: f32,
|
||||
pub(crate) y: f32,
|
||||
}
|
||||
|
||||
impl Hash for RXingResultPoint {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.x.to_string().hash(state);
|
||||
self.y.to_string().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for RXingResultPoint {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x == other.x && self.y == other.y
|
||||
}
|
||||
}
|
||||
impl Eq for RXingResultPoint {}
|
||||
|
||||
impl RXingResultPoint {
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub const fn with_single(x: f32) -> Self {
|
||||
Self { x, y: x }
|
||||
}
|
||||
@@ -47,12 +51,8 @@ impl std::ops::AddAssign for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl<'a> Sum<&'a RXingResultPoint> for RXingResultPoint {
|
||||
fn sum<I: Iterator<Item = &'a RXingResultPoint>>(iter: I) -> Self {
|
||||
let mut add = RXingResultPoint { x: 0.0, y: 0.0 };
|
||||
for n in iter {
|
||||
add += *n;
|
||||
}
|
||||
add
|
||||
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::default(), |acc, &p| acc + p)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ impl ResultPoint for RXingResultPoint {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint {
|
||||
fn into_rxing_result_point(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ impl fmt::Display for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl std::ops::Sub<RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
@@ -87,19 +87,8 @@ impl std::ops::Sub<RXingResultPoint> for RXingResultPoint {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<&RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn sub(self, rhs: &Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Self {
|
||||
@@ -110,9 +99,9 @@ impl std::ops::Neg for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl std::ops::Add<RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
@@ -121,9 +110,9 @@ impl std::ops::Add<RXingResultPoint> for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl std::ops::Mul<RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs.x,
|
||||
y: self.y * rhs.y,
|
||||
@@ -132,7 +121,7 @@ impl std::ops::Mul<RXingResultPoint> for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
@@ -143,7 +132,7 @@ impl std::ops::Mul<f32> for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl std::ops::Mul<i32> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: i32) -> Self::Output {
|
||||
Self {
|
||||
@@ -157,7 +146,7 @@ impl std::ops::Mul<RXingResultPoint> for i32 {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn mul(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
Self::Output {
|
||||
x: rhs.x * self as f32,
|
||||
y: rhs.y * self as f32,
|
||||
}
|
||||
@@ -168,29 +157,7 @@ impl std::ops::Mul<RXingResultPoint> for f32 {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn mul(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
x: rhs.x * self,
|
||||
y: rhs.y * self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<&RXingResultPoint> for f32 {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn mul(self, rhs: &RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
x: rhs.x * self,
|
||||
y: rhs.y * self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<&mut RXingResultPoint> for f32 {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn mul(self, rhs: &mut RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
Self::Output {
|
||||
x: rhs.x * self,
|
||||
y: rhs.y * self,
|
||||
}
|
||||
@@ -209,66 +176,57 @@ impl std::ops::Div<f32> for RXingResultPoint {
|
||||
}
|
||||
|
||||
impl RXingResultPoint {
|
||||
pub fn dot(a: RXingResultPoint, b: RXingResultPoint) -> f32 {
|
||||
a.x * b.x + a.y * b.y
|
||||
pub fn dot(self, p: Self) -> f32 {
|
||||
self.x * p.x + self.y * p.y
|
||||
}
|
||||
|
||||
pub fn cross(a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
a.x * b.y - b.x * a.y
|
||||
pub fn cross(self, p: Self) -> f32 {
|
||||
self.x * p.y - p.x * self.y
|
||||
}
|
||||
|
||||
/// L1 norm
|
||||
pub fn sumAbsComponent(p: &RXingResultPoint) -> f32 {
|
||||
(p.x).abs() + (p.y).abs()
|
||||
pub fn sumAbsComponent(self) -> f32 {
|
||||
self.x.abs() + self.y.abs()
|
||||
}
|
||||
|
||||
/// L2 norm
|
||||
pub fn length(p: RXingResultPoint) -> f32 {
|
||||
(Self::dot(p, p)).sqrt()
|
||||
pub fn length(self) -> f32 {
|
||||
Self::dot(self, self).sqrt()
|
||||
}
|
||||
|
||||
/// L-inf norm
|
||||
pub fn maxAbsComponent(p: &RXingResultPoint) -> f32 {
|
||||
let a = (p.x).abs();
|
||||
let b = (p.y).abs();
|
||||
|
||||
if a > b {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
|
||||
// return std::cmp::max((p.x).abs(), (p.y).abs());
|
||||
pub fn maxAbsComponent(self) -> f32 {
|
||||
f32::max(self.x.abs(), self.y.abs())
|
||||
}
|
||||
|
||||
pub fn distance(a: RXingResultPoint, b: RXingResultPoint) -> f32 {
|
||||
Self::length(a - b)
|
||||
pub fn distance(self, p: Self) -> f32 {
|
||||
Self::length(self - p)
|
||||
}
|
||||
|
||||
/// Calculate a floating point pixel coordinate representing the 'center' of the pixel.
|
||||
/// This is sort of the inverse operation of the PointI(PointF) conversion constructor.
|
||||
/// See also the documentation of the GridSampler API.
|
||||
#[inline(always)]
|
||||
pub fn centered(p: &RXingResultPoint) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
x: (p.x).floor() + 0.5,
|
||||
y: (p.y).floor() + 0.5,
|
||||
pub fn centered(self) -> Self {
|
||||
Self {
|
||||
x: self.x.floor() + 0.5,
|
||||
y: self.y.floor() + 0.5,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normalized(d: RXingResultPoint) -> RXingResultPoint {
|
||||
d / Self::length(d)
|
||||
pub fn normalized(self) -> Self {
|
||||
self / Self::length(self)
|
||||
}
|
||||
|
||||
pub fn bresenhamDirection(d: &RXingResultPoint) -> RXingResultPoint {
|
||||
*d / Self::maxAbsComponent(d)
|
||||
pub fn bresenhamDirection(self) -> Self {
|
||||
self / Self::maxAbsComponent(self)
|
||||
}
|
||||
|
||||
pub fn mainDirection(d: RXingResultPoint) -> RXingResultPoint {
|
||||
if (d.x).abs() > (d.y).abs() {
|
||||
Self::new(d.x, 0.0)
|
||||
pub fn mainDirection(self) -> Self {
|
||||
if self.x.abs() > self.y.abs() {
|
||||
Self::new(self.x, 0.0)
|
||||
} else {
|
||||
Self::new(0.0, d.y)
|
||||
Self::new(0.0, self.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user