use crate::{KernelRefusal, KernelStage, NurbsSurface, OrRefuse};
use super::*;
use super::rim_welds::fit_rim_circle;
pub(super) fn tangent_rim_round_enabled() -> bool {
switch!("BREP_OFFSET_TANGENT_RIM_ROUND", false)
}
pub(super) fn circular_rim_round(
rim: &EdgeRecord,
opening: &FaceRecord,
distance: f64,
tolerance: f64,
) -> Result<Option<BrepSolid>, KernelRefusal> {
let Some(circle) = fit_rim_circle(rim, tolerance)? else {
return Ok(None);
};
if !(distance > 0.0) || distance >= circle.radius {
return Ok(None);
}
let [u0, u1] = opening.surface.domain_u().or_refuse(KernelStage::Refine, "domain_u")?;
let [v0, v1] = opening.surface.domain_v().or_refuse(KernelStage::Refine, "domain_v")?;
let probe = opening.surface.evaluate((u0 + u1) * 0.5, (v0 + v1) * 0.5).or_refuse(KernelStage::Refine, "evaluate")?;
let side = probe.sub(circle.center).dot(circle.axis);
if side.abs() <= tolerance {
return Ok(None);
}
let axis = if side < 0.0 { circle.axis } else { circle.axis.scale(-1.0) };
let surface = crate::make_torus_surface(circle.center, axis, circle.radius, distance).or_refuse(KernelStage::Refine, "make_torus_surface")?;
Ok(Some(tube_sheet(surface, 0.5, 1.0)?))
}
pub(super) fn tube_sheet(surface: NurbsSurface, v_from: f64, v_to: f64) -> Result<BrepSolid, KernelRefusal> {
let [u0, u1] = surface.domain_u().or_refuse(KernelStage::Refine, "domain_u")?;
let near = surface.evaluate(u0, v_from).or_refuse(KernelStage::Refine, "evaluate")?;
let far = surface.evaluate(u0, v_to).or_refuse(KernelStage::Refine, "evaluate")?;
let near_circle = surface.iso_curve_v(v_from).or_refuse(KernelStage::Refine, "iso_curve_v")?;
let far_circle = surface.iso_curve_v(v_to).or_refuse(KernelStage::Refine, "iso_curve_v")?;
let seam = surface.iso_curve_u(u0).or_refuse(KernelStage::Refine, "iso_curve_u")?;
let [c0, c1] = near_circle.domain().or_refuse(KernelStage::Refine, "domain")?;
let [f0, f1] = far_circle.domain().or_refuse(KernelStage::Refine, "domain")?;
let line = |a: f64, b: f64, c: f64, d: f64| crate::sweep_topology::parameter_line(a, b, c, d).or_refuse(KernelStage::Refine, "parameter_line");
let mut face = FaceRecord {
id: 128,
surface,
same_sense: true,
name: None,
loops: vec![LoopRecord {
id: 127,
coedges: vec![
CoedgeRecord { id: 101, edge_id: 10, forward: true, pcurve: line(u0, v_from, u1, v_from)? },
CoedgeRecord { id: 102, edge_id: 12, forward: true, pcurve: line(u1, v_from, u1, v_to)? },
CoedgeRecord { id: 103, edge_id: 11, forward: false, pcurve: line(u1, v_to, u0, v_to)? },
CoedgeRecord { id: 104, edge_id: 12, forward: false, pcurve: line(u0, v_to, u0, v_from)? },
],
}],
};
if parameter_space_area(&face).or_refuse(KernelStage::Refine, "parameter_space_area")? < 0.0 {
let loop_record = &mut face.loops[0];
loop_record.coedges.reverse();
for coedge in &mut loop_record.coedges {
coedge.forward = !coedge.forward;
coedge.pcurve = coedge.pcurve.reversed().or_refuse(KernelStage::Refine, "reversed")?;
}
}
Ok(BrepSolid {
mass_properties_cache: Default::default(),
cells: Default::default(),
id: 130,
genus: 0,
kind: crate::BodyKind::Sheet,
vertices: vec![VertexRecord { id: 1, point: near }, VertexRecord { id: 2, point: far }],
edges: vec![
EdgeRecord { id: 10, curve: near_circle, t0: c0, t1: c1, start_vertex_id: 1, end_vertex_id: 1, degenerate: false, name: None },
EdgeRecord { id: 11, curve: far_circle, t0: f0, t1: f1, start_vertex_id: 2, end_vertex_id: 2, degenerate: false, name: None },
EdgeRecord { id: 12, curve: seam, t0: v_from, t1: v_to, start_vertex_id: 1, end_vertex_id: 2, degenerate: false, name: None },
],
shells: vec![ShellRecord { id: 129, faces: vec![face] }],
})
}