Skip to main content

brepkit_blend/
lib.rs

1//! Walking-based fillet and chamfer engine.
2//!
3//! This crate implements blend surface computation using a
4//! Newton-Raphson walking algorithm. It produces G1-continuous fillet
5//! and chamfer surfaces for all combinations of analytic and NURBS faces.
6
7#[allow(dead_code)]
8pub(crate) mod adaptive_tolerance;
9pub(crate) mod analytic;
10pub(crate) mod blend_func;
11pub(crate) mod builder_utils;
12pub mod chamfer_builder;
13pub(crate) mod corner;
14pub mod fillet_builder;
15#[allow(dead_code)]
16pub(crate) mod g1_chain;
17pub mod radius_law;
18pub(crate) mod section;
19pub(crate) mod spherical_triangle;
20pub(crate) mod spine;
21pub(crate) mod stripe;
22pub(crate) mod trimmer;
23pub(crate) mod walker;
24
25use brepkit_topology::edge::EdgeId;
26use brepkit_topology::face::FaceId;
27use brepkit_topology::solid::SolidId;
28use brepkit_topology::vertex::VertexId;
29
30/// Error type for blend operations.
31#[derive(Debug, thiserror::Error)]
32pub enum BlendError {
33    /// No initial solution found at the spine start.
34    #[error("no start solution at edge {edge:?}, t={t}")]
35    StartSolutionFailure {
36        /// The edge where the start solution failed.
37        edge: EdgeId,
38        /// The parameter value at the failure point.
39        t: f64,
40    },
41
42    /// Walker diverged during marching.
43    #[error("walking failure at edge {edge:?}, t={t}, residual={residual}")]
44    WalkingFailure {
45        /// The edge where walking failed.
46        edge: EdgeId,
47        /// The parameter value at the failure point.
48        t: f64,
49        /// The residual norm at failure.
50        residual: f64,
51    },
52
53    /// Generated surface is twisted or self-intersecting.
54    #[error("twisted surface on stripe {stripe_idx}")]
55    TwistedSurface {
56        /// Index of the stripe that is twisted.
57        stripe_idx: usize,
58    },
59
60    /// Radius too large for the edge geometry.
61    #[error("radius too large for edge {edge:?}: max={max_radius}")]
62    RadiusTooLarge {
63        /// The edge for which the radius is too large.
64        edge: EdgeId,
65        /// The maximum allowable radius.
66        max_radius: f64,
67    },
68
69    /// Face trimming failed.
70    #[error("trimming failure on face {face:?}")]
71    TrimmingFailure {
72        /// The face where trimming failed.
73        face: FaceId,
74    },
75
76    /// Corner solver failed at vertex.
77    #[error("corner failure at vertex {vertex:?}")]
78    CornerFailure {
79        /// The vertex where the corner solver failed.
80        vertex: VertexId,
81    },
82
83    /// Surface type not supported.
84    #[error("unsupported surface on face {face:?}: {surface_tag}")]
85    UnsupportedSurface {
86        /// The face with the unsupported surface.
87        face: FaceId,
88        /// A description of the unsupported surface type.
89        surface_tag: String,
90    },
91
92    /// Topology error from underlying operations.
93    #[error(transparent)]
94    Topology(#[from] brepkit_topology::TopologyError),
95
96    /// Math error from underlying computations.
97    #[error(transparent)]
98    Math(#[from] brepkit_math::MathError),
99}
100
101/// Result of a blend operation.
102pub struct BlendResult {
103    /// The resulting solid.
104    pub solid: SolidId,
105    /// Edges that were successfully blended.
106    pub succeeded: Vec<EdgeId>,
107    /// Edges that failed with diagnostic info.
108    pub failed: Vec<(EdgeId, BlendError)>,
109    /// Whether this is a partial result (some edges failed).
110    pub is_partial: bool,
111}