fix(drawing/bend): Improve handling of almost equal points in perp_dot_product

This commit is contained in:
Ellen Emilia Anna Zscheile 2025-05-20 00:05:37 +02:00
parent d553fd6ba7
commit ee19ae934f
2 changed files with 16 additions and 13 deletions

View File

@ -10,8 +10,6 @@ use core::fmt;
use rstar::{RTree, AABB}; use rstar::{RTree, AABB};
use thiserror::Error; use thiserror::Error;
use crate::graph::{GenericIndex, GetPetgraphIndex};
use crate::math::NoTangents;
use crate::{ use crate::{
drawing::{ drawing::{
band::BandTermsegIndex, band::BandTermsegIndex,
@ -32,17 +30,18 @@ use crate::{
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight, SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
}, },
}, },
graph::MakeRef,
};
use crate::{
geometry::{ geometry::{
edit::{ApplyGeometryEdit, GeometryEdit}, edit::{ApplyGeometryEdit, GeometryEdit},
primitive::{AccessPrimitiveShape, PrimitiveShape}, primitive::{AccessPrimitiveShape, PrimitiveShape},
recording_with_rtree::RecordingGeometryWithRtree, recording_with_rtree::RecordingGeometryWithRtree,
shape::MeasureLength,
with_rtree::BboxedIndex, with_rtree::BboxedIndex,
AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel, AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel,
GetLayer, GetOffset, GetSetPos, GetWidth, GetLayer, GetOffset, GetSetPos, GetWidth,
}, },
graph::MakeRef,
graph::{GenericIndex, GetPetgraphIndex},
math::NoTangents,
math::RotationSense, math::RotationSense,
}; };
@ -814,6 +813,9 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
predicate: &impl Fn(&Self, PrimitiveIndex, PrimitiveIndex) -> bool, predicate: &impl Fn(&Self, PrimitiveIndex, PrimitiveIndex) -> bool,
) -> Result<Cane, DrawingException> { ) -> Result<Cane, DrawingException> {
let seg_to = self.add_dot_with_infringement_filtering(recorder, dot_weight, predicate)?; let seg_to = self.add_dot_with_infringement_filtering(recorder, dot_weight, predicate)?;
// we just checked that we can insert a dot there
let to = self.add_dot_infringably(recorder, dot_weight);
let seg = self let seg = self
.add_seg_with_infringement_filtering( .add_seg_with_infringement_filtering(
recorder, recorder,
@ -824,14 +826,7 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
) )
.inspect_err(|_| { .inspect_err(|_| {
self.recording_geometry_with_rtree self.recording_geometry_with_rtree
.remove_dot(recorder, seg_to.into()); .remove_dot(recorder, to.into());
})?;
let to = self
.add_dot_with_infringement_filtering(recorder, dot_weight, predicate)
.inspect_err(|_| {
self.recording_geometry_with_rtree
.remove_seg(recorder, seg.into());
self.recording_geometry_with_rtree self.recording_geometry_with_rtree
.remove_dot(recorder, seg_to.into()); .remove_dot(recorder, seg_to.into());
})?; })?;
@ -859,6 +854,9 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
.remove_dot(recorder, seg_to.into()); .remove_dot(recorder, seg_to.into());
})?; })?;
#[cfg(debug_assertions)]
approx::assert_abs_diff_eq!(bend.primitive(self).shape().length(), 0.0);
Ok(Cane { Ok(Cane {
seg, seg,
dot: seg_to, dot: seg_to,

View File

@ -251,5 +251,10 @@ pub fn dot_product(v1: Point, v2: Point) -> f64 {
/// and its magnitude, since the resulting vector is always perpendicular to /// and its magnitude, since the resulting vector is always perpendicular to
/// the plane anyway. /// the plane anyway.
pub fn perp_dot_product(v1: Point, v2: Point) -> f64 { pub fn perp_dot_product(v1: Point, v2: Point) -> f64 {
// catch numerical rounding errors
if approx::relative_eq!(v1.x(), v2.x()) && approx::relative_eq!(v1.y(), v2.y()) {
return 0.0;
}
v1.x() * v2.y() - v1.y() * v2.x() v1.x() * v2.y() - v1.y() * v2.x()
} }