diff --git a/crates/difftest/src/units/query_face_p2.rs b/crates/difftest/src/units/query_face_p2.rs index 1b076d3c58..8f927a5de4 100644 --- a/crates/difftest/src/units/query_face_p2.rs +++ b/crates/difftest/src/units/query_face_p2.rs @@ -509,11 +509,7 @@ fn pc_block(pc: &PointClassification) -> Vec { /// The shim's `put_pc` block for a curve classification's point classification: only /// faces, edges and vertices have an export index (other objects are `-3, -1`). -fn cc_pc_block( - k: &Kernel, - objects: &Objects<'_>, - pc: &PointClassification, -) -> Result, HarnessError> { +fn cc_pc_block(k: &Kernel, objects: &Objects<'_>, pc: &PointClassification) -> Result, HarnessError> { let (kind, index) = match pc.object() { None => (0.0, -1.0), Some(H::Face(f)) => (1.0, f64::from(f.index())), @@ -781,16 +777,7 @@ fn rust(i: &Inputs) -> Result { let uv = Point2::new(a(0), a(1)); let d1 = Extent2d::from_points(Point2::new(a(4), a(5)), Point2::new(a(6), a(7))); let d2 = Extent2d::from_points(Point2::new(a(9), a(10)), Point2::new(a(11), a(12))); - match qf::classify_param_on_faces( - &k, - &mut b.clone(), - uv, - zone_tol3d(&k, *tol), - f1, - &d1, - f2, - &d2, - ) { + match qf::classify_param_on_faces(&k, &mut b.clone(), uv, zone_tol3d(&k, *tol), f1, &d1, f2, &d2) { Ok(w) => Ok(Output::new().values("which", vec![f64::from(w)])), Err(e) => Ok(rust_err(&e)), } @@ -814,36 +801,21 @@ fn rust(i: &Inputs) -> Result { let line = match BSplineCurve::create_line_segment(u64::from(*dim), p, q) { Ok(line) => line, Err(SolidError::Upstream { code, .. }) => { - return Ok( - Output::new().values("curve_classification", vec![-3.0, f64::from(code)]) - ) + return Ok(Output::new().values("curve_classification", vec![-3.0, f64::from(code)])) } Err(e) => return Ok(rust_err(&e)), }; let curve = Curve::from(line); let interval = curve.natural_interval(); let objects = Objects { brep: b, curve }; - let mut cc: CurveClassification = CurveClassification::with_curve_interval( - &k, - H::Curve, - interval, - zone_tol3d(&k, *tol), - ); - let (status, modified) = match qf::curve_on_classify( - &k, - b, - f, - &objects, - *do_pc, - &mut cc, - *big_gaps, - *check3d, - true, - ) { - Ok(modified) => (0.0, modified), - Err(SolidError::Upstream { code, .. }) => (f64::from(code), false), - Err(e) => return Ok(rust_err(&e)), - }; + let mut cc: CurveClassification = + CurveClassification::with_curve_interval(&k, H::Curve, interval, zone_tol3d(&k, *tol)); + let (status, modified) = + match qf::curve_on_classify(&k, b, f, &objects, *do_pc, &mut cc, *big_gaps, *check3d, true) { + Ok(modified) => (0.0, modified), + Err(SolidError::Upstream { code, .. }) => (f64::from(code), false), + Err(e) => return Ok(rust_err(&e)), + }; let mut o = vec![status, flag(modified), cc.size() as f64]; for iv in cc.intervals() { o.extend([iv.interval.min(), iv.interval.max()]); diff --git a/crates/difftest/src/units/topology_brep_p10.rs b/crates/difftest/src/units/topology_brep_p10.rs index ddceaa6fb0..6cfe19412f 100644 --- a/crates/difftest/src/units/topology_brep_p10.rs +++ b/crates/difftest/src/units/topology_brep_p10.rs @@ -269,11 +269,7 @@ fn set_field(d: &mut BrepData, field: i64, index: i64, value: i64) -> Result<(), // an index past the array is a no-op match field { 0 => d.faces.get_mut(i).into_iter().for_each(|r| r.surface = u), - 1 => d - .faces - .get_mut(i) - .into_iter() - .for_each(|r| r.start_loop = u), + 1 => d.faces.get_mut(i).into_iter().for_each(|r| r.start_loop = u), 2 => d.loops.get_mut(i).into_iter().for_each(|r| r.start_eu = u), 3 => d.loops.get_mut(i).into_iter().for_each(|r| r.vertex = u), 4 => d.edgeuses.get_mut(i).into_iter().for_each(|r| r.edge = u), diff --git a/crates/solidcore/src/blend/fillet_geom/p2.rs b/crates/solidcore/src/blend/fillet_geom/p2.rs index 7449333cb0..408278cec7 100644 --- a/crates/solidcore/src/blend/fillet_geom/p2.rs +++ b/crates/solidcore/src/blend/fillet_geom/p2.rs @@ -366,6 +366,31 @@ fn corner_type(corner: FilletCornerId) -> Result { ) } +/// The `SmBSplineCurve` (base) of a curve kind derived from it (`SmLine`, +/// `SmEllipse`/`SmCircle`, `SmHyperbola`, `SmParabola`), `None` for the others. +const fn b_spline_base(c: &Curve) -> Option<&BSplineCurve> { + match c.kind() { + CurveKind::BSpline(b) => Some(b), + CurveKind::Line(l) => Some(l.base()), + CurveKind::Ellipse(e) => Some(e.base()), + CurveKind::Hyperbola(h) => Some(h.base()), + CurveKind::Parabola(p) => Some(p.base()), + _ => None, + } +} + +/// [`b_spline_base`], mutably: the receiver of a non-virtual `SmBSplineCurve` method. +fn b_spline_base_mut(c: &mut Curve) -> Option<&mut BSplineCurve> { + match c.kind_mut() { + CurveKind::BSpline(b) => Some(b), + CurveKind::Line(l) => Some(l.base_mut()), + CurveKind::Ellipse(e) => Some(e.base_mut()), + CurveKind::Hyperbola(h) => Some(h.base_mut()), + CurveKind::Parabola(p) => Some(p.base_mut()), + _ => None, + } +} + /// `SmFilletConcaveNxNCorner::TestRailRailInterpolationCurve` (unit /// `blend.fillet_corner_p1`). fn corner_test_rail_rail_interpolation_curve( @@ -1982,7 +2007,9 @@ impl FilletBrep { interpolate_endpts_and_tangents(start_pnt, end_pnt, &mut start_vec, &mut end_vec, 3)? }; - let mut curve_3d: Option; + // p3DCurve, an SmBSplineCurve: a B-spline, or the line / conic iso curve + // LiftCurve's sm_ExtractIsoCurve makes + let mut curve_3d: Option; let mut uv_curve: Option; if create_crv_on_3d { // Compute UV-curve by projecting 3d curve onto the surface @@ -1994,10 +2021,7 @@ impl FilletBrep { return Err(SolidError::sm_err(OP)); } uv_curve = uv_curves.into_iter().next(); - curve_3d = match c3.into_kind() { - CurveKind::BSpline(b) => Some(b), - _ => None, - }; + curve_3d = Some(c3); } else { let mut uv = new_curve; // its status is ignored upstream @@ -2023,25 +2047,16 @@ impl FilletBrep { // Reparametrize the curve with arc-length for non-blend type if fsg_type != FilletSurfaceGeneratorType::BlendCurve { - c3.reparametrize_with_arc_length()?; + b_spline_base_mut(&mut c3) + .ok_or_else(|| SolidError::null_pointer(OP))? + .reparametrize_with_arc_length()?; // Reproject the 3d curve back onto the surface - let c3c = Curve::from(c3); - let uv_curves = surface_drop_curve( - k, - face_srf, - &uv_domain, - &c3c, - &c3c.natural_interval(), - tol, - )?; + let uv_curves = + surface_drop_curve(k, face_srf, &uv_domain, &c3, &c3.natural_interval(), tol)?; if uv_curves.len() != 1 { return Err(SolidError::sm_err(OP)); } uv_curve = uv_curves.into_iter().next(); - c3 = match c3c.into_kind() { - CurveKind::BSpline(b) => b, - _ => return Err(SolidError::null_pointer(OP)), - }; } curve_3d = Some(c3); } @@ -2050,6 +2065,7 @@ impl FilletBrep { if corner_type(corner)? == FilletCornerType::NByNConcave { let c3 = curve_3d .as_ref() + .and_then(b_spline_base) .ok_or_else(|| SolidError::null_pointer(OP))?; // Test and see if this edge intersects with the original corner if corner_test_rail_rail_interpolation_curve(corner, c3)? { @@ -2114,7 +2130,7 @@ impl FilletBrep { // set p3DCurve as this FilletEdge's geometry (side effect: the edge uses' UV // trim curves go), then the mate edge use's UV curve let curve_3d = curve_3d.ok_or_else(|| SolidError::null_pointer(OP))?; - set_edge_curve(self.brep_mut(), e, Some(Curve::from(curve_3d)))?; + set_edge_curve(self.brep_mut(), e, Some(curve_3d))?; let mate_eu = primary_edgeuse(self.brep(), e)? .and_then(|p| eu1::mate(self.brep(), p).ok().flatten()) .ok_or_else(|| SolidError::null_pointer(OP))?; diff --git a/crates/solidcore/src/blend/fillet_geom/p4.rs b/crates/solidcore/src/blend/fillet_geom/p4.rs index 2e37e9bf0e..509aae11b0 100644 --- a/crates/solidcore/src/blend/fillet_geom/p4.rs +++ b/crates/solidcore/src/blend/fillet_geom/p4.rs @@ -2098,7 +2098,7 @@ impl FilletBrep { false, )?; let crv_ivl = lifted.curve.natural_interval(); - set_edge_curve(self.brep_mut(), rail, Some(Curve::from(lifted.curve)))?; + set_edge_curve(self.brep_mut(), rail, Some(lifted.curve))?; edge::set_interval(self.brep_mut(), rail, &crv_ivl)?; self.set_edgeuse_uv_curve(mate, Some(Curve::from(new_uv_curve)), true, true)?; }