fix(bpt): compare rotation rows across angle wrap

This commit is contained in:
Karim Jerbi committed 2026-10-18 19:56:01 +01:00
1 parent f74e1e8bd3
commit 9d2f4e592a
3 files changed
+33 -4

No files matched your search

+15 -1
View File
@@ -221,7 +221,21 @@ impl OpenCADStudio {
.then(|| { .then(|| {
view.rows view.rows
.iter() .iter()
.position(|r| r.iter().zip(&values).all(|(a, b)| (a - b).abs() <= 1e-9)) .position(|row| {
row.iter().zip(&values).zip(&view.columns).all(
|((row_value, value), column)| {
let difference = if column
.connection_name
.eq_ignore_ascii_case("UpdatedAngle")
{
crate::scene::block_actions::angle_distance(*row_value, *value)
} else {
(row_value - value).abs()
};
difference <= 1e-9
},
)
})
}) })
.flatten(); .flatten();
self.tabs[i].selected_grips.push(GripDef { self.tabs[i].selected_grips.push(GripDef {
+10 -3
View File
@@ -11,6 +11,14 @@ use glam::DVec3;
pub(crate) mod instance; pub(crate) mod instance;
mod representation; mod representation;
mod stretch; mod stretch;
/// Smallest signed distance between two angles in radians, accounting for the
/// wrap at ±π. Used for BPT rotation snapping and current-row detection.
pub(crate) fn angle_distance(a: f64, b: f64) -> f64 {
((a - b + std::f64::consts::PI).rem_euclid(std::f64::consts::TAU)
- std::f64::consts::PI)
.abs()
}
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@@ -1097,9 +1105,8 @@ fn evaluate_impl(
.iter() .iter()
.filter_map(|row| row.get(col).copied()) .filter_map(|row| row.get(col).copied())
.min_by(|a, b| { .min_by(|a, b| {
(a - angle) angle_distance(*a, angle)
.abs() .total_cmp(&angle_distance(*b, angle))
.total_cmp(&(b - angle).abs())
.then_with(|| a.total_cmp(b)) .then_with(|| a.total_cmp(b))
}) })
{ {
+8
View File
@@ -3,6 +3,14 @@ use crate::scene::{block_distance_parameter as distance, block_point_parameter a
use codec::{DwgReader, DwgWriter, DxfReader, DxfWriter}; use codec::{DwgReader, DwgWriter, DxfReader, DxfWriter};
use std::io::Cursor; use std::io::Cursor;
#[test]
fn rotation_table_angles_match_across_pi_wrap() {
let near_positive_pi = std::f64::consts::PI - 0.01;
let near_negative_pi = -std::f64::consts::PI + 0.01;
assert!((super::angle_distance(near_positive_pi, near_negative_pi) - 0.02).abs() < 1e-12);
assert!(super::angle_distance(near_positive_pi, 0.0) > 3.0);
}
fn fixture() -> (CadDocument, Handle, Vec<Handle>) { fn fixture() -> (CadDocument, Handle, Vec<Handle>) {
let mut scene = Scene::new(); let mut scene = Scene::new();
scene.define_block_raw( scene.define_block_raw(