Skip to content

Commit

Permalink
Merge pull request #20 from dwmunster/bugfix/rotated-rectangle
Browse files Browse the repository at this point in the history
Handle Ambiguity in RotatedRectangleDemo Positions
  • Loading branch information
TobiasJacob authored Jun 3, 2024
2 parents 397d85b + ef87a06 commit 0a4cf5f
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 108 deletions.
103 changes: 76 additions & 27 deletions src/examples/test_rectangle_rotated.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::error::Error;
use std::{cell::RefCell, rc::Rc};

use nalgebra::Vector2;
Expand Down Expand Up @@ -160,19 +161,91 @@ impl RotatedRectangleDemo {
point_reference,
}
}

pub fn check(&self, eps: f64) -> Result<(), Box<dyn Error>> {
let point_a = self.point_a.as_ref().borrow().data();
let point_b = self.point_b.as_ref().borrow().data();
let point_c = self.point_c.as_ref().borrow().data();
let point_d = self.point_d.as_ref().borrow().data();
let point_reference = self.point_reference.as_ref().borrow().data();

let s2 = f64::sqrt(2.0);
let s22 = s2 / 2.;

if (point_reference - Vector2::new(1.0, 0.0)).norm() >= eps {
return Err(format!("point_reference not solved: {:?}", point_reference).into());
}

if (point_a - Vector2::new(0.0, 0.0)).norm() >= eps {
return Err(format!("point_a not solved: {:?}", point_a).into());
}

// Problem is under-constrained, look for b above or below the x-axis
if point_b[1] < 0. {
if (point_b - Vector2::new(s2, -s2)).norm() >= eps {
return Err(format!("point_b (below) not solved: {:?}", point_b).into());
}
// Point c can either be up-and-right of b or down-and-left of b
if point_c[1] < point_b[1] {
// Point c is down-and-left of b
if (point_c - Vector2::new(-s22, -5. * s22)).norm() >= eps {
return Err(format!("point_c (down,left) not solved: {:?}", point_c).into());
}

if (point_d - Vector2::new(-3. * s22, -3. * s22)).norm() >= eps {
return Err(format!("point_d (down,left) not solved: {:?}", point_d).into());
}
} else {
// Point c is up-and-right of b
if (point_c - Vector2::new(5. * s22, s22)).norm() >= eps {
return Err(format!("point_c (up,right) not solved: {:?}", point_c).into());
}

if (point_d - Vector2::new(3. * s22, 3. * s22)).norm() >= eps {
return Err(format!("point_d (up,right) not solved: {:?}", point_d).into());
}
}
} else {
if (point_b - Vector2::new(s2, s2)).norm() >= eps {
return Err(format!("point_b (above) not solved: {:?}", point_b).into());
}
// Point c can either be up-and-left of b or down-and-right of b
if point_c[1] > point_b[1] {
// Point c is up-and-left of b
if (point_c - Vector2::new(-s22, 5. * s22)).norm() >= eps {
return Err(format!("point_c (up,left) not solved: {:?}", point_c).into());
}

if (point_d - Vector2::new(-3. * s22, 3. * s22)).norm() >= eps {
return Err(format!("point_d (up,left) not solved: {:?}", point_d).into());
}
} else {
// Point c is down-and-right of b
if (point_c - Vector2::new(5. * s22, -s22)).norm() >= eps {
return Err(format!("point_c (down,right) not solved: {:?}", point_c).into());
}

if (point_d - Vector2::new(3. * s22, -3. * s22)).norm() >= eps {
return Err(format!("point_d (down,right) not solved: {:?}", point_d).into());
}
}
}

Ok(())
}
}

#[cfg(test)]
mod tests {
use nalgebra::Vector2;
use std::error::Error;

use crate::{
examples::test_rectangle_rotated::RotatedRectangleDemo,
solvers::{bfgs_solver::BFGSSolver, Solver},
};

#[test]
pub fn test_rectangle_rotated() {
pub fn test_rectangle_rotated() -> Result<(), Box<dyn Error>> {
let rectangle = RotatedRectangleDemo::new();

// Now solve the sketch
Expand All @@ -188,30 +261,6 @@ mod tests {
rectangle.point_reference.as_ref().borrow()
);

assert!(
(rectangle.point_a.as_ref().borrow().data() - Vector2::new(0.0, 0.0)).norm() < 1e-5
);
assert!(
(rectangle.point_b.as_ref().borrow().data()
- Vector2::new(f64::sqrt(2.0), -f64::sqrt(2.0)))
.norm()
< 1e-5
);
assert!(
(rectangle.point_c.as_ref().borrow().data()
- Vector2::new(5.0 / f64::sqrt(2.0), 1.0 / f64::sqrt(2.0)))
.norm()
< 1e-5
);
assert!(
(rectangle.point_d.as_ref().borrow().data()
- Vector2::new(3.0 / f64::sqrt(2.0), 3.0 / f64::sqrt(2.0)))
.norm()
< 1e-5
);
assert!(
(rectangle.point_reference.as_ref().borrow().data() - Vector2::new(1.0, 0.0)).norm()
< 1e-5
);
rectangle.check(1e-5)
}
}
30 changes: 3 additions & 27 deletions src/solvers/bfgs_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ impl Solver for BFGSSolver {

#[cfg(test)]
mod tests {
use nalgebra::Vector2;
use std::error::Error;

use crate::{
examples::test_rectangle_rotated::RotatedRectangleDemo,
solvers::{bfgs_solver::BFGSSolver, Solver},
};

#[test]
pub fn test_bfgs_solver() {
pub fn test_bfgs_solver() -> Result<(), Box<dyn Error>> {
let rectangle = RotatedRectangleDemo::new();

// Now solve the sketch
Expand All @@ -124,30 +124,6 @@ mod tests {
rectangle.point_reference.as_ref().borrow()
);

assert!(
(rectangle.point_a.as_ref().borrow().data() - Vector2::new(0.0, 0.0)).norm() < 1e-5
);
assert!(
(rectangle.point_b.as_ref().borrow().data()
- Vector2::new(f64::sqrt(2.0), -f64::sqrt(2.0)))
.norm()
< 1e-5
);
assert!(
(rectangle.point_c.as_ref().borrow().data()
- Vector2::new(5.0 / f64::sqrt(2.0), 1.0 / f64::sqrt(2.0)))
.norm()
< 1e-5
);
assert!(
(rectangle.point_d.as_ref().borrow().data()
- Vector2::new(3.0 / f64::sqrt(2.0), 3.0 / f64::sqrt(2.0)))
.norm()
< 1e-5
);
assert!(
(rectangle.point_reference.as_ref().borrow().data() - Vector2::new(1.0, 0.0)).norm()
< 1e-5
);
rectangle.check(1e-5)
}
}
30 changes: 3 additions & 27 deletions src/solvers/gauss_newton_solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ impl Solver for GaussNewtonSolver {

#[cfg(test)]
mod tests {
use nalgebra::Vector2;
use std::error::Error;

use crate::{
examples::test_rectangle_rotated::RotatedRectangleDemo,
solvers::{gauss_newton_solver::GaussNewtonSolver, Solver},
};

#[test]
pub fn test_gauss_newton_solver() {
pub fn test_gauss_newton_solver() -> Result<(), Box<dyn Error>> {
let rectangle = RotatedRectangleDemo::new();

// Now solve the sketch
Expand All @@ -84,30 +84,6 @@ mod tests {
rectangle.point_reference.as_ref().borrow()
);

assert!(
(rectangle.point_a.as_ref().borrow().data() - Vector2::new(0.0, 0.0)).norm() < 0.01
);
assert!(
(rectangle.point_b.as_ref().borrow().data()
- Vector2::new(f64::sqrt(2.0), -f64::sqrt(2.0)))
.norm()
< 0.1
);
assert!(
(rectangle.point_c.as_ref().borrow().data()
- Vector2::new(5.0 / f64::sqrt(2.0), 1.0 / f64::sqrt(2.0)))
.norm()
< 0.1
);
assert!(
(rectangle.point_d.as_ref().borrow().data()
- Vector2::new(3.0 / f64::sqrt(2.0), 3.0 / f64::sqrt(2.0)))
.norm()
< 0.1
);
assert!(
(rectangle.point_reference.as_ref().borrow().data() - Vector2::new(1.0, 0.0)).norm()
< 0.1
);
rectangle.check(1e-1)
}
}
30 changes: 3 additions & 27 deletions src/solvers/levenberg_marquardt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ impl Solver for LevenbergMarquardtSolver {

#[cfg(test)]
mod tests {
use nalgebra::Vector2;
use std::error::Error;

use crate::{
examples::test_rectangle_rotated::RotatedRectangleDemo,
solvers::{levenberg_marquardt::LevenbergMarquardtSolver, Solver},
};

#[test]
pub fn test_levenberg_marquardt_solver() {
pub fn test_levenberg_marquardt_solver() -> Result<(), Box<dyn Error>> {
let rectangle = RotatedRectangleDemo::new();

// Now solve the sketch
Expand All @@ -95,30 +95,6 @@ mod tests {
rectangle.point_reference.as_ref().borrow()
);

assert!(
(rectangle.point_a.as_ref().borrow().data() - Vector2::new(0.0, 0.0)).norm() < 0.01
);
assert!(
(rectangle.point_b.as_ref().borrow().data()
- Vector2::new(f64::sqrt(2.0), -f64::sqrt(2.0)))
.norm()
< 0.1
);
assert!(
(rectangle.point_c.as_ref().borrow().data()
- Vector2::new(5.0 / f64::sqrt(2.0), 1.0 / f64::sqrt(2.0)))
.norm()
< 0.1
);
assert!(
(rectangle.point_d.as_ref().borrow().data()
- Vector2::new(3.0 / f64::sqrt(2.0), 3.0 / f64::sqrt(2.0)))
.norm()
< 0.1
);
assert!(
(rectangle.point_reference.as_ref().borrow().data() - Vector2::new(1.0, 0.0)).norm()
< 0.1
);
rectangle.check(1e-1)
}
}

0 comments on commit 0a4cf5f

Please sign in to comment.