Skip to main content

bin_packing/
cut_plan.rs

1//! Cut sequencing and step generation for finished layouts.
2//!
3//! Cut planning is a post-processor on solver output: given an
4//! [`OneDSolution`](crate::one_d::OneDSolution) or
5//! [`TwoDSolution`](crate::two_d::TwoDSolution), produce an ordered
6//! sequence of cuts that a shop operator can execute, scored against a
7//! preset cost model.
8//!
9//! Entry points:
10//! - [`crate::one_d::cut_plan::plan_cuts`]
11//! - [`crate::two_d::cut_plan::plan_cuts`]
12
13use serde::{Deserialize, Serialize};
14use thiserror::Error;
15
16/// Errors reported by the cut planner.
17///
18/// Distinct from [`BinPackingError`](crate::BinPackingError) so that
19/// callers using the solver but not the cut planner are unaffected.
20#[derive(Debug, Clone, PartialEq, Eq, Error, Serialize, Deserialize)]
21#[serde(tag = "type", rename_all = "snake_case")]
22#[non_exhaustive]
23pub enum CutPlanError {
24    /// The caller selected a table-saw or panel-saw preset but the
25    /// layout is not guillotine-compatible (a single-blade machine
26    /// cannot produce it).
27    #[error(
28        "layout on sheet `{sheet_name}` is not guillotine-compatible and cannot be cut on a single-blade machine"
29    )]
30    NonGuillotineNotCuttable {
31        /// Name of the offending sheet layout.
32        sheet_name: String,
33    },
34    /// The caller supplied invalid cost overrides (negative value, NaN,
35    /// or infinity) or a mismatched configuration.
36    #[error("invalid cut-plan options: {0}")]
37    InvalidOptions(String),
38}
39
40/// `Result` alias for cut-plan operations.
41pub type Result<T> = core::result::Result<T, CutPlanError>;