forked from 1b-agent/opencadstudio-upstream
fix(bpt): compare rotation rows across angle wrap
This commit is contained in:
1 parent
f74e1e8bd3
commit
9d2f4e592a
3 files changed
+33
-4
No files matched your search
+15
-1
@@ -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 {
|
||||||
|
|||||||
@@ -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))
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in new issue
Block a user