Merge pull request #1302: Preserve valid zero-radius curves

This commit is contained in:
Hakan Seven committed 2026-09-16 09:37:48 +03:00
commit 306d5d0957
2 files changed
+33 -9

No files matched your search

+2 -1
View File
@@ -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
View File
@@ -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]