mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 12:22:34 +00:00
Promote Quadrilateral to default
The library now uses the `Quadrilateral` struct when handling sets of four points in `GridSampler` and `PerspectiveTransform`
This commit is contained in:
@@ -19,17 +19,20 @@
|
||||
// import org.junit.Assert;
|
||||
// import org.junit.Test;
|
||||
|
||||
use crate::point;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
// public final class PerspectiveTransformTestCase extends Assert {
|
||||
use super::PerspectiveTransform;
|
||||
use super::{PerspectiveTransform, Quadrilateral};
|
||||
|
||||
static EPSILON: f32 = 1.0E-4f32;
|
||||
|
||||
#[test]
|
||||
fn test_square_to_quadrilateral() {
|
||||
let pt = PerspectiveTransform::squareToQuadrilateral(2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0);
|
||||
let square = Quadrilateral::new(point(2.0, 3.0), point(10.0, 3.0), point(16.0, 15.0), point(4.0,9.0));
|
||||
let pt = PerspectiveTransform::squareToQuadrilateral(square);
|
||||
assert_point_equals(2.0, 3.0, 0.0, 0.0, &pt);
|
||||
assert_point_equals(10.0, 4.0, 1.0, 0.0, &pt);
|
||||
assert_point_equals(4.0, 9.0, 0.0, 1.0, &pt);
|
||||
@@ -40,10 +43,10 @@ fn test_square_to_quadrilateral() {
|
||||
|
||||
#[test]
|
||||
fn test_quadrilateral_to_quadrilateral() {
|
||||
let pt = PerspectiveTransform::quadrilateralToQuadrilateral(
|
||||
2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0, 103.0, 110.0, 300.0, 120.0, 290.0, 270.0, 150.0,
|
||||
280.0,
|
||||
);
|
||||
let quad1 = Quadrilateral::new(point(2.0, 3.0), point(10.0, 4.0), point(16.0, 15.0), point(4.0, 9.0));
|
||||
let quad2 = Quadrilateral::new(point(103.0, 110.0), point(300.0, 120.0), point(290.0, 270.0), point(150.0,280.0));
|
||||
let pt = PerspectiveTransform::quadrilateralToQuadrilateral(quad1, quad2);
|
||||
|
||||
assert_point_equals(103.0, 110.0, 2.0, 3.0, &pt);
|
||||
assert_point_equals(300.0, 120.0, 10.0, 4.0, &pt);
|
||||
assert_point_equals(290.0, 270.0, 16.0, 15.0, &pt);
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
// import com.google.zxing.NotFoundException;
|
||||
|
||||
use crate::common::Result;
|
||||
use crate::{common::Result};
|
||||
use crate::Exceptions;
|
||||
|
||||
use super::{BitMatrix, GridSampler, PerspectiveTransform};
|
||||
use super::{BitMatrix, GridSampler, PerspectiveTransform, Quadrilateral, SamplerControl};
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
@@ -35,29 +35,14 @@ impl GridSampler for DefaultGridSampler {
|
||||
image: &BitMatrix,
|
||||
dimensionX: u32,
|
||||
dimensionY: u32,
|
||||
p1ToX: f32,
|
||||
p1ToY: f32,
|
||||
p2ToX: f32,
|
||||
p2ToY: f32,
|
||||
p3ToX: f32,
|
||||
p3ToY: f32,
|
||||
p4ToX: f32,
|
||||
p4ToY: f32,
|
||||
p1FromX: f32,
|
||||
p1FromY: f32,
|
||||
p2FromX: f32,
|
||||
p2FromY: f32,
|
||||
p3FromX: f32,
|
||||
p3FromY: f32,
|
||||
p4FromX: f32,
|
||||
p4FromY: f32,
|
||||
dst: Quadrilateral,
|
||||
src:Quadrilateral
|
||||
) -> Result<BitMatrix> {
|
||||
let transform = PerspectiveTransform::quadrilateralToQuadrilateral(
|
||||
p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX,
|
||||
p2FromY, p3FromX, p3FromY, p4FromX, p4FromY,
|
||||
dst, src,
|
||||
);
|
||||
|
||||
self.sample_grid(image, dimensionX, dimensionY, &transform)
|
||||
self.sample_grid(image, dimensionX, dimensionY, &[SamplerControl::new(dimensionX, dimensionY, transform)])
|
||||
}
|
||||
|
||||
fn sample_grid(
|
||||
@@ -65,7 +50,7 @@ impl GridSampler for DefaultGridSampler {
|
||||
image: &BitMatrix,
|
||||
dimensionX: u32,
|
||||
dimensionY: u32,
|
||||
transform: &PerspectiveTransform,
|
||||
controls: &[SamplerControl]
|
||||
) -> Result<BitMatrix> {
|
||||
if dimensionX == 0 || dimensionY == 0 {
|
||||
return Err(Exceptions::NOT_FOUND);
|
||||
@@ -83,7 +68,7 @@ impl GridSampler for DefaultGridSampler {
|
||||
points[x + 1] = i_value;
|
||||
x += 2;
|
||||
}
|
||||
transform.transform_points_single(&mut points);
|
||||
controls.first().unwrap().transform.transform_points_single(&mut points);
|
||||
// Quick check to see if points transformed to something inside the image;
|
||||
// sufficient to check the endpoints
|
||||
self.checkAndNudgePoints(image, &mut points)?;
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
// import com.google.zxing.NotFoundException;
|
||||
|
||||
use crate::common::Result;
|
||||
use crate::Exceptions;
|
||||
use crate::{common::Result, Point};
|
||||
use crate::{Exceptions, point};
|
||||
|
||||
use super::{BitMatrix, PerspectiveTransform};
|
||||
use super::{BitMatrix, PerspectiveTransform, Quadrilateral};
|
||||
|
||||
/**
|
||||
* Implementations of this class can, given locations of finder patterns for a QR code in an
|
||||
@@ -93,22 +93,8 @@ pub trait GridSampler {
|
||||
image: &BitMatrix,
|
||||
dimensionX: u32,
|
||||
dimensionY: u32,
|
||||
p1ToX: f32,
|
||||
p1ToY: f32,
|
||||
p2ToX: f32,
|
||||
p2ToY: f32,
|
||||
p3ToX: f32,
|
||||
p3ToY: f32,
|
||||
p4ToX: f32,
|
||||
p4ToY: f32,
|
||||
p1FromX: f32,
|
||||
p1FromY: f32,
|
||||
p2FromX: f32,
|
||||
p2FromY: f32,
|
||||
p3FromX: f32,
|
||||
p3FromY: f32,
|
||||
p4FromX: f32,
|
||||
p4FromY: f32,
|
||||
dst: Quadrilateral,
|
||||
src:Quadrilateral
|
||||
) -> Result<BitMatrix>;
|
||||
|
||||
fn sample_grid(
|
||||
@@ -116,7 +102,7 @@ pub trait GridSampler {
|
||||
image: &BitMatrix,
|
||||
dimensionX: u32,
|
||||
dimensionY: u32,
|
||||
transform: &PerspectiveTransform,
|
||||
controls: &[SamplerControl]
|
||||
) -> Result<BitMatrix>;
|
||||
|
||||
/**
|
||||
@@ -195,3 +181,15 @@ pub trait GridSampler {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SamplerControl {
|
||||
pub p0: Point,
|
||||
pub p1: Point,
|
||||
pub transform: PerspectiveTransform
|
||||
}
|
||||
|
||||
impl SamplerControl {
|
||||
pub fn new( width: u32, height: u32, transform: PerspectiveTransform ) -> Self {
|
||||
Self{ p0: point(0.0, 0.0), p1: point(width as f32, height as f32), transform }
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,9 @@ pub use hybrid_binarizer::*;
|
||||
mod eci;
|
||||
pub use eci::*;
|
||||
|
||||
mod quad;
|
||||
pub use quad::*;
|
||||
|
||||
#[cfg(feature = "otsu_level")]
|
||||
mod otsu_level_binarizer;
|
||||
#[cfg(feature = "otsu_level")]
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
|
||||
// package com.google.zxing.common;
|
||||
|
||||
use std::ops::Mul;
|
||||
|
||||
use crate::point;
|
||||
|
||||
use super::Quadrilateral;
|
||||
|
||||
/**
|
||||
* <p>This class implements a perspective transform in two dimensions. Given four source and four
|
||||
* destination points, it will compute the transformation implied between them. The code is based
|
||||
@@ -63,27 +69,18 @@ impl PerspectiveTransform {
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn quadrilateralToQuadrilateral(
|
||||
x0: f32,
|
||||
y0: f32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
x3: f32,
|
||||
y3: f32,
|
||||
x0p: f32,
|
||||
y0p: f32,
|
||||
x1p: f32,
|
||||
y1p: f32,
|
||||
x2p: f32,
|
||||
y2p: f32,
|
||||
x3p: f32,
|
||||
y3p: f32,
|
||||
dst: Quadrilateral,
|
||||
src: Quadrilateral
|
||||
) -> Self {
|
||||
let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
|
||||
// let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
// let s_to_q =
|
||||
// PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
||||
|
||||
let q_to_s = PerspectiveTransform::quadrilateralToSquare(dst);
|
||||
let s_to_q =
|
||||
PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
||||
s_to_q.times(&q_to_s)
|
||||
PerspectiveTransform::squareToQuadrilateral(src);
|
||||
s_to_q * q_to_s
|
||||
}
|
||||
|
||||
pub fn transform_points_single(&self, points: &mut [f32]) {
|
||||
@@ -122,35 +119,29 @@ impl PerspectiveTransform {
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn squareToQuadrilateral(
|
||||
x0: f32,
|
||||
y0: f32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
x3: f32,
|
||||
y3: f32,
|
||||
square: Quadrilateral
|
||||
) -> Self {
|
||||
let dx3 = x0 - x1 + x2 - x3;
|
||||
let dy3 = y0 - y1 + y2 - y3;
|
||||
if dx3 == 0.0 && dy3 == 0.0 {
|
||||
let [p0, p1, p2, p3 ] = square.0;
|
||||
|
||||
let d3 = p0 - p1 + p2 - p3;
|
||||
if d3 == point(0.0,0.0) {
|
||||
// Affine
|
||||
PerspectiveTransform::new(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0)
|
||||
PerspectiveTransform::new(p1.x - p0.x, p2.x - p1.x, p0.x, p1.y - p0.y, p2.y - p1.y, p0.y, 0.0, 0.0, 1.0)
|
||||
} else {
|
||||
let dx1 = x1 - x2;
|
||||
let dx2 = x3 - x2;
|
||||
let dy1 = y1 - y2;
|
||||
let dy2 = y3 - y2;
|
||||
let denominator = dx1 * dy2 - dx2 * dy1;
|
||||
let a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
|
||||
let a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
|
||||
|
||||
let d1 = p1 - p2;
|
||||
let d2 = p3 - p2;
|
||||
|
||||
let denominator = d1.cross(d2);
|
||||
let a13 = (d3.x * d2.y - d2.x * d3.y) / denominator;
|
||||
let a23 = (d1.x * d3.y - d3.x * d1.y) / denominator;
|
||||
PerspectiveTransform::new(
|
||||
x1 - x0 + a13 * x1,
|
||||
x3 - x0 + a23 * x3,
|
||||
x0,
|
||||
y1 - y0 + a13 * y1,
|
||||
y3 - y0 + a23 * y3,
|
||||
y0,
|
||||
p1.x - p0.x + a13 * p1.x,
|
||||
p3.x - p0.x + a23 * p3.x,
|
||||
p0.x,
|
||||
p1.y - p0.y + a13 * p1.y,
|
||||
p3.y - p0.y + a23 * p3.y,
|
||||
p0.y,
|
||||
a13,
|
||||
a23,
|
||||
1.0,
|
||||
@@ -160,17 +151,10 @@ impl PerspectiveTransform {
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn quadrilateralToSquare(
|
||||
x0: f32,
|
||||
y0: f32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
x3: f32,
|
||||
y3: f32,
|
||||
quad: Quadrilateral
|
||||
) -> Self {
|
||||
// Here, the adjoint serves as the inverse
|
||||
PerspectiveTransform::squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint()
|
||||
PerspectiveTransform::squareToQuadrilateral(quad).buildAdjoint()
|
||||
}
|
||||
|
||||
fn buildAdjoint(&self) -> Self {
|
||||
@@ -187,18 +171,22 @@ impl PerspectiveTransform {
|
||||
self.a11 * self.a22 - self.a12 * self.a21,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn times(&self, other: &Self) -> Self {
|
||||
impl Mul for PerspectiveTransform {
|
||||
type Output = PerspectiveTransform;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
PerspectiveTransform::new(
|
||||
self.a11 * other.a11 + self.a21 * other.a12 + self.a31 * other.a13,
|
||||
self.a11 * other.a21 + self.a21 * other.a22 + self.a31 * other.a23,
|
||||
self.a11 * other.a31 + self.a21 * other.a32 + self.a31 * other.a33,
|
||||
self.a12 * other.a11 + self.a22 * other.a12 + self.a32 * other.a13,
|
||||
self.a12 * other.a21 + self.a22 * other.a22 + self.a32 * other.a23,
|
||||
self.a12 * other.a31 + self.a22 * other.a32 + self.a32 * other.a33,
|
||||
self.a13 * other.a11 + self.a23 * other.a12 + self.a33 * other.a13,
|
||||
self.a13 * other.a21 + self.a23 * other.a22 + self.a33 * other.a23,
|
||||
self.a13 * other.a31 + self.a23 * other.a32 + self.a33 * other.a33,
|
||||
self.a11 * rhs.a11 + self.a21 * rhs.a12 + self.a31 * rhs.a13,
|
||||
self.a11 * rhs.a21 + self.a21 * rhs.a22 + self.a31 * rhs.a23,
|
||||
self.a11 * rhs.a31 + self.a21 * rhs.a32 + self.a31 * rhs.a33,
|
||||
self.a12 * rhs.a11 + self.a22 * rhs.a12 + self.a32 * rhs.a13,
|
||||
self.a12 * rhs.a21 + self.a22 * rhs.a22 + self.a32 * rhs.a23,
|
||||
self.a12 * rhs.a31 + self.a22 * rhs.a32 + self.a32 * rhs.a33,
|
||||
self.a13 * rhs.a11 + self.a23 * rhs.a12 + self.a33 * rhs.a13,
|
||||
self.a13 * rhs.a21 + self.a23 * rhs.a22 + self.a33 * rhs.a23,
|
||||
self.a13 * rhs.a31 + self.a23 * rhs.a32 + self.a33 * rhs.a33,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
217
src/common/quad.rs
Normal file
217
src/common/quad.rs
Normal file
@@ -0,0 +1,217 @@
|
||||
use crate::Point;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Quadrilateral(pub [Point; 4]);
|
||||
|
||||
impl Quadrilateral {
|
||||
// using Base = std::array<T, 4>;
|
||||
// using Base::at;
|
||||
// public:
|
||||
// using Point = T;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new(tl:Point, tr: Point, br: Point, bl: Point) -> Self {
|
||||
Self([tl,tr,br,bl])
|
||||
}
|
||||
// pub fn with_f32( tl:f32, tr:f32, br:f32, bl:f32) -> Self {
|
||||
// Self([tl, tr,br, bl ])
|
||||
// }
|
||||
|
||||
pub fn with_points(tl: Point, tr: Point, br: Point, bl: Point) -> Self {
|
||||
Self([tl, tr, br, bl])
|
||||
}
|
||||
|
||||
pub fn top_left(&self) -> &Point {
|
||||
&self.0[0]
|
||||
} //const noexcept { return at(0); }
|
||||
pub fn top_right(&self) -> &Point {
|
||||
&self.0[1]
|
||||
} //const noexcept { return at(1); }
|
||||
pub fn bottom_right(&self) -> &Point {
|
||||
&self.0[2]
|
||||
} //const noexcept { return at(2); }
|
||||
pub fn bottom_left(&self) -> &Point {
|
||||
&self.0[3]
|
||||
} //const noexcept { return at(3); }
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn orientation(&self) -> f64 {
|
||||
let centerLine =
|
||||
(*self.top_right() + *self.bottom_right()) - (*self.top_left() + *self.bottom_left());
|
||||
if (centerLine == Point { x: 0.0, y: 0.0 }) {
|
||||
return 0.0;
|
||||
}
|
||||
let centerLineF = Point::normalized(centerLine);
|
||||
f32::atan2(centerLineF.y, centerLineF.x).into()
|
||||
}
|
||||
pub fn points(&self) -> &[Point] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Quadrilateral {
|
||||
#[allow(dead_code)]
|
||||
pub fn rectangle(width: i32, height: i32, margin: Option<i32>) -> Quadrilateral {
|
||||
let margin = margin.unwrap_or(0);
|
||||
|
||||
Quadrilateral([
|
||||
Point {
|
||||
x: margin as f32,
|
||||
y: margin as f32,
|
||||
},
|
||||
Point {
|
||||
x: width as f32 - margin as f32,
|
||||
y: margin as f32,
|
||||
},
|
||||
Point {
|
||||
x: width as f32 - margin as f32,
|
||||
y: height as f32 - margin as f32,
|
||||
},
|
||||
Point {
|
||||
x: margin as f32,
|
||||
y: height as f32 - margin as f32,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn centered_square(size: i32) -> Quadrilateral {
|
||||
Self::scale(
|
||||
&Quadrilateral([
|
||||
Point { x: -1.0, y: -1.0 },
|
||||
Point { x: 1.0, y: -1.0 },
|
||||
Point { x: 1.0, y: 1.0 },
|
||||
Point { x: -1.0, y: 1.0 },
|
||||
]),
|
||||
size / 2,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn line(y: i32, xStart: i32, xStop: i32) -> Quadrilateral {
|
||||
Quadrilateral([
|
||||
Point {
|
||||
x: xStart as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
Point {
|
||||
x: xStop as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
Point {
|
||||
x: xStop as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
Point {
|
||||
x: xStart as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_convex(&self) -> bool {
|
||||
let N = self.0.len();
|
||||
let mut sign = false;
|
||||
|
||||
let mut m = f32::INFINITY;
|
||||
let mut M = 0.0_f32;
|
||||
|
||||
for i in 0..N
|
||||
// for(int i = 0; i < N; i++)
|
||||
{
|
||||
let d1 = self.0[(i + 2) % N] - self.0[(i + 1) % N];
|
||||
let d2 = self.0[i] - self.0[(i + 1) % N];
|
||||
let cp = d1.cross(d2);
|
||||
|
||||
m = if m.abs() > cp { cp } else { m.abs() };
|
||||
|
||||
M = if M.abs() > cp { M.abs() } else { cp };
|
||||
// m = std::cmp::min((m).abs(), cp);
|
||||
// M = std::cmp::max((M).abs(), cp);
|
||||
|
||||
if i == 0 {
|
||||
sign = cp > 0.0;
|
||||
} else if sign != (cp > 0.0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// It turns out being convex is not enough to prevent a "numerical instability"
|
||||
// that can cause the corners being projected inside the image boundaries but
|
||||
// some points near the corners being projected outside. This has been observed
|
||||
// where one corner is almost in line with two others. The M/m ratio is below 2
|
||||
// for the complete existing sample set. For very "skewed" QRCodes a value of
|
||||
// around 3 is realistic. A value of 14 has been observed to trigger the
|
||||
// instability.
|
||||
M / m < 4.0
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn scale(&self, factor: i32) -> Quadrilateral {
|
||||
Quadrilateral([
|
||||
self.0[0] * factor as f32,
|
||||
self.0[1] * factor as f32,
|
||||
self.0[2] * factor as f32,
|
||||
self.0[3] * factor as f32,
|
||||
])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn center(&self) -> Point {
|
||||
let reduced: Point = self.0.iter().sum();
|
||||
let size = self.0.len() as f32;
|
||||
reduced / size
|
||||
// return Reduce(q) / Size(q);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn rotated_corners(&self, n: Option<i32>, mirror: Option<bool>) -> Quadrilateral {
|
||||
let n = if let Some(n) = n { n } else { 1 };
|
||||
|
||||
let mirror = if let Some(m) = mirror { m } else { false };
|
||||
|
||||
let mut res = self.clone();
|
||||
res.0.rotate_left(((n + 4) % 4) as usize);
|
||||
// std::rotate_copy(q.begin(), q.begin() + ((n + 4) % 4), q.end(), res.begin());
|
||||
if mirror {
|
||||
res.0.swap(1, 3);
|
||||
}
|
||||
// {std::swap(res[1], res[3]);}
|
||||
res
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_inside(&self, p: Point) -> 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..self.0.len()
|
||||
// for (int i = 0; i < Size(q); ++i)
|
||||
{
|
||||
if Point::cross(p - self.0[i], self.0[(i + 1) % self.0.len()] - self.0[i]) < 0.0 {
|
||||
neg += 1;
|
||||
} else {
|
||||
pos += 1;
|
||||
}
|
||||
// (cross(p - q[i], q[(i + 1) % Size(q)] - q[i]) < 0 ? neg : pos)++;
|
||||
}
|
||||
|
||||
pos == 0 || neg == 0
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn have_intersecting_bounding_boxes(&self, b: &Quadrilateral) -> bool {
|
||||
// TODO: this is only a quick and dirty approximation that works for the trivial standard cases
|
||||
let x = b.top_right().x < self.top_left().x || b.top_left().x > self.top_right().x;
|
||||
let y = b.bottom_left().y < self.top_left().y || b.top_left().y > self.bottom_left().y;
|
||||
|
||||
!(x || y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Quadrilateral {
|
||||
fn default() -> Self {
|
||||
Self([Point { x: 0.0, y: 0.0 }; 4])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user