diff --git a/src/scene/pipeline/circle_gpu.rs b/src/scene/pipeline/circle_gpu.rs index a59f9614e..33104fcbf 100644 --- a/src/scene/pipeline/circle_gpu.rs +++ b/src/scene/pipeline/circle_gpu.rs @@ -306,7 +306,12 @@ pub fn extract_circle_instances( /// Allocation-free check whether this wire consists entirely of analytical circle/arc instances. pub fn can_extract_circle_instances(wire: &crate::scene::WireModel) -> bool { - if wire.tangent_geoms.is_empty() + // Patterned circular curves stay on the regular wire pipeline. Its dash + // path is shared with LINE/POLYLINE and remains consistent across file + // open/save cycles. The analytical circle path is reserved for continuous + // curves until its linetype phase/LOD behaviour is fully equivalent. + if wire.pattern_length > 0.0 + || wire.tangent_geoms.is_empty() || !wire.fill_tris.is_empty() || wire.fill_is_3d || !wire.text_verts.is_empty() @@ -344,7 +349,8 @@ pub fn extract_circle_instances_into( draw_depth: f32, out: &mut Vec, ) -> bool { - if wire.tangent_geoms.is_empty() + if wire.pattern_length > 0.0 + || wire.tangent_geoms.is_empty() || !wire.fill_tris.is_empty() || wire.fill_is_3d || !wire.text_verts.is_empty() diff --git a/src/scene/pipeline/wire_arena.rs b/src/scene/pipeline/wire_arena.rs index 563047eee..8951b309d 100644 --- a/src/scene/pipeline/wire_arena.rs +++ b/src/scene/pipeline/wire_arena.rs @@ -1774,6 +1774,58 @@ mod tests { assert_eq!(partitioned.regular.len(), 1); } + #[test] + fn patterned_circle_and_arc_stay_in_regular_wire_pipeline() { + use crate::scene::model::wire_model::TangentGeom; + + let mut circle = WireModel::default(); + circle.points = vec![ + [10.0, 0.0, 0.0], + [0.0, 10.0, 0.0], + [-10.0, 0.0, 0.0], + ]; + circle.tangent_geoms.push(TangentGeom::PlanarCircle { + center: [0.0, 0.0, 0.0], + axis_x: [1.0, 0.0, 0.0], + axis_y: [0.0, 1.0, 0.0], + radius: 10.0, + }); + circle.pattern_length = 1.0; + circle.pattern = [0.5, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; + + let mut arc = WireModel::default(); + arc.points = vec![ + [10.0, 0.0, 0.0], + [7.0, 7.0, 0.0], + [0.0, 10.0, 0.0], + ]; + arc.tangent_geoms.push(TangentGeom::Arc { + center: [0.0, 0.0, 0.0], + axis_x: [1.0, 0.0, 0.0], + axis_y: [0.0, 1.0, 0.0], + radius: 10.0, + start_angle: 0.0, + end_angle: std::f64::consts::FRAC_PI_2, + }); + arc.pattern_length = 1.0; + arc.pattern = [0.5, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; + + let wires = vec![circle, arc]; + let depth_map = rustc_hash::FxHashMap::default(); + let partitioned = partition_wires(&wires, &depth_map); + + assert_eq!( + partitioned.circle_instances.len(), + 0, + "patterned circular curves must not use the analytical circle path" + ); + assert_eq!( + partitioned.regular.len(), + 2, + "patterned circle and arc must fall back to the regular dashed-wire path" + ); + } + #[test] fn partition_wires_partitions_thick_and_tapered_arcs() { use crate::scene::model::wire_model::TangentGeom;