forked from 1b-agent/opencadstudio-upstream
Merge pull request #1302: Preserve valid zero-radius curves
This commit is contained in:
commit
306d5d0957
2 files changed
+33
-9
No files matched your search
@@ -1417,7 +1417,8 @@ mod tests {
|
||||
doc.add_entity(acadrust::EntityType::Circle(good)).unwrap();
|
||||
let mut corrupt = acadrust::entities::Circle::new();
|
||||
corrupt.center = acadrust::types::Vector3::new(1.0, 1.0, 0.0);
|
||||
corrupt.radius = 0.0; // io::is_entity_corrupt rejects a zero-radius circle
|
||||
// An absurd radius is rejected; a zero radius is valid.
|
||||
corrupt.radius = 1.0e11;
|
||||
doc.add_entity(acadrust::EntityType::Circle(corrupt))
|
||||
.unwrap();
|
||||
let bytes = crate::io::save_to_bytes(&doc, "dxf", doc.version)
|
||||
|
||||
+31
-8
@@ -2023,6 +2023,8 @@ fn sync_current_styles_on_save(doc: &mut CadDocument) {
|
||||
// `purge_corrupt_entities` scans the document and removes any entity that
|
||||
// fails a cheap sanity check, returning the number dropped so the caller can
|
||||
// surface it to the UI / log.
|
||||
//
|
||||
// Keep valid degenerate geometry: dropping it would trigger strict-open recovery.
|
||||
|
||||
fn finite_unit_normal(n: &acadrust::types::Vector3) -> bool {
|
||||
let (x, y, z) = (n.x, n.y, n.z);
|
||||
@@ -2080,20 +2082,15 @@ pub(crate) fn is_entity_corrupt(e: &EntityType) -> bool {
|
||||
|| p.vertices.iter().any(|v| !finite_vec3(&v.location))
|
||||
}
|
||||
E::Line(l) => !finite_vec3(&l.start) || !finite_vec3(&l.end),
|
||||
// Zero-radius curves are valid and have bounded kernel tessellation.
|
||||
E::Circle(c) => {
|
||||
!finite_vec3(&c.center)
|
||||
|| !finite_coord(c.radius)
|
||||
// Reject zero- or near-zero circles: they tessellate into a
|
||||
// degenerate curve the tessellator cannot sample.
|
||||
|| c.radius.abs() < 1.0e-10
|
||||
|| c.radius.abs() > 1.0e10
|
||||
!finite_vec3(&c.center) || !finite_coord(c.radius) || c.radius.abs() > 1.0e10
|
||||
}
|
||||
E::Arc(a) => {
|
||||
!finite_vec3(&a.center)
|
||||
|| !finite_coord(a.radius)
|
||||
|| !a.start_angle.is_finite()
|
||||
|| !a.end_angle.is_finite()
|
||||
|| a.radius.abs() < 1.0e-10
|
||||
|| a.radius.abs() > 1.0e10
|
||||
|| !finite_unit_normal(&a.normal)
|
||||
}
|
||||
@@ -2343,7 +2340,7 @@ mod layer_roundtrip_tests {
|
||||
#[cfg(test)]
|
||||
mod corrupt_guard_tests {
|
||||
use super::*;
|
||||
use acadrust::entities::{Arc, EntityType, Spline};
|
||||
use acadrust::entities::{Arc, Circle, EntityType, Spline};
|
||||
use acadrust::types::Vector3;
|
||||
|
||||
// Small but finite arcs are valid records. Kernel tessellation is bounded,
|
||||
@@ -2383,6 +2380,32 @@ mod corrupt_guard_tests {
|
||||
assert!(!is_entity_corrupt(&EntityType::Arc(a)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_zero_radius_circle_and_arc() {
|
||||
let mut c = Circle::new();
|
||||
c.center = Vector3::new(206.2, 150.7, 0.0);
|
||||
c.radius = 0.0;
|
||||
assert!(!is_entity_corrupt(&EntityType::Circle(c)));
|
||||
|
||||
let mut a = Arc::new();
|
||||
a.center = Vector3::new(223.5, 174.5, 0.0);
|
||||
a.radius = 0.0;
|
||||
a.start_angle = 0.0;
|
||||
a.end_angle = 0.0;
|
||||
a.normal = Vector3::new(0.0, 0.0, 1.0);
|
||||
assert!(!is_entity_corrupt(&EntityType::Arc(a)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drops_absurd_radius_circle() {
|
||||
let mut c = Circle::new();
|
||||
c.radius = 1.0e11;
|
||||
assert!(is_entity_corrupt(&EntityType::Circle(c)));
|
||||
let mut c = Circle::new();
|
||||
c.radius = f64::NAN;
|
||||
assert!(is_entity_corrupt(&EntityType::Circle(c)));
|
||||
}
|
||||
|
||||
// Parser desync emits 100_000-control-point splines; building a kernel
|
||||
// NURBS from one and tessellating it OOMs. The control-point cap rejects it.
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user