Struct BoolmeshBoolean

Source
pub struct BoolmeshBoolean;
Expand description

Mesh boolean built on the algorithm absorbed from boolmesh (pure Rust, glam-only, MPL-2.0).

Adopted in docs/adr/0014 and absorbed into this crate’s private csg module by docs/adr/0047. This type owns conversion and contract enforcement; no csg type is part of the public API, so the kernel can be replaced without a consumer noticing.

Implementations§

Source§

impl BoolmeshBoolean

Source

pub const ID: BackendId

Stable identifier used in errors and explicit provider selection.

Source

pub const fn new() -> Self

Construct the provider.

Source

pub fn subtract_boxes_analytic( &self, subject: &TriMesh, tools: &[TriMesh], options: &ExecutionOptions, max_cells: usize, ) -> GeomResult<Option<BooleanOutcome>>

Subtract axis-aligned box cutters from an axis-aligned box subject using an exact closed-form construction, bypassing the general solver.

Returns Ok(None) when the operands are outside this path’s competence, so the caller falls back to MeshBoolean::subtract_many rather than receiving an approximate answer. Declining cases:

  • subject or any tool is not an axis-aligned box (recognised structurally – triangle count, corner lattice, and face planes – not by bounding box, since every mesh has one of those)
  • no tools, or no tool overlapping the subject
  • the induced grid would exceed max_cells
§Why opt-in rather than automatic

Dispatching on shape automatically would make output topology depend on input in a way the caller cannot predict: the same wall would produce different triangle counts depending on whether its openings happened to be axis-aligned. Callers that want the speed ask for it and handle the None; callers that want one predictable code path never see this.

§Guarantees

The result is watertight by construction (adjacent cells address shared grid vertices by integer index) and deterministic across processes (vertex identity is an ordered map, not a randomly-seeded hash map).

The returned evidence has BooleanEvidence::analytic_path set, so a caller can tell this result apart from a general-solver result.

Source§

impl BoolmeshBoolean

Source

pub fn boolean_fast( &self, subject: &TriMesh, tool: &TriMesh, operation: BooleanOperator, options: &ExecutionOptions, ) -> GeomResult<BooleanOutcome>

Alternative to MeshBoolean::boolean using a cheaper winding-number classification for the same result.

See csg::boolean03::kernel03::winding03_fast’s doc comment for the guarantee: not an approximation, but a bug in edge-break detection would mislabel a whole connected component instead of one vertex. Opt-in rather than the default until this has run against a wider correctness corpus than the differential tests already covering it.

SymmetricDifference is refused rather than silently composed from three slow-path calls: a caller asking for the fast path should get it or a clear refusal, not a surprise fallback.

Trait Implementations§

Source§

impl Backend for BoolmeshBoolean

Source§

fn descriptor(&self) -> BackendDescriptor

Runtime descriptor and capability inventory.
Source§

impl Clone for BoolmeshBoolean

Source§

fn clone(&self) -> BoolmeshBoolean

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BoolmeshBoolean

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BoolmeshBoolean

Source§

fn default() -> BoolmeshBoolean

Returns the “default value” for a type. Read more
Source§

impl MeshBoolean for BoolmeshBoolean

Source§

fn determinism(&self) -> Determinism

Honest about the general path, which is not byte-reproducible.

Upstream boolmesh dedups vertices through a randomly-seeded HashMap, so its output ordering varies between processes even single-threaded. That is the same root cause documented in Self::subtract_boxes_analytic, which avoids it with a BTreeMap. The general path therefore cannot claim Determinism::Bitwise at any thread count, and enabling parallel does not make it weaker than it already is.

Determinism::Topological is the honest ceiling: the result’s connectivity is stable, its vertex ordering is not. Callers needing byte reproducibility use Self::subtract_boxes_analytic, whose ordered vertex identity makes it reproducible across processes.

Source§

fn scratch_requirement(&self) -> ScratchRequirement

Measured, not guessed.

boolmesh builds a Morton collider and intersection tables sized by the combined input. It exposes no bound, so this was measured directly with a counting global allocator (src/bin/scratch_probe/) across all four operations at 24 to 1,536 input triangles, after one discarded warmup call so the first operation measured is not charged for process startup (#110):

 triangles   peak bytes   bytes/triangle   worst operation
        24        52424             2184   SymmetricDifference
        96        98920             1030   SymmetricDifference
       384       343768              895   SymmetricDifference
      1536      1349668              878   SymmetricDifference

Consumption is linear in input size, converging to under 1 KiB per triangle; the higher ratio at small inputs is fixed setup cost being divided by few triangles. SymmetricDifference is worst because it is composed from three passes and holds intermediates alive.

The declared bound is 4 KiB per triangle: about 1.9x the worst observed ratio, as headroom for allocator variance and future operand shapes. tests/scratch_bound.rs measures the same workloads and fails if any peak exceeds it. A declared bound that is occasionally too low is worse than Unbounded, because it makes a budget look enforced when it is not.

Source§

fn cancellation_granularity(&self) -> CancellationGranularity

boolmesh takes no cancellation handle, so nothing can interrupt a single boolean once it starts. Declared honestly: the batch override polls between groups, which is the only real poll point available.

Source§

fn subtract_many( &self, subject: &TriMesh, tools: &[TriMesh], options: &ExecutionOptions, ) -> GeomResult<BooleanOutcome>

Group mutually disjoint cutters and remove each group with one boolean, instead of one boolean per cutter.

Rests on (S \ A) \ B == S \ (A union B) and on a concatenation of disjoint solids being their union. Bounding-box grouping over-separates but never wrongly fuses, so the result is identical to the sequential default – gated by volume equality in tests/batch.rs.

Source§

fn union_many( &self, solids: &[TriMesh], options: &ExecutionOptions, ) -> GeomResult<BooleanOutcome>

Union many solids in one batch so implementations can choose a reduction order. Read more
Source§

fn boolean( &self, subject: &TriMesh, tool: &TriMesh, operation: BooleanOperator, options: &ExecutionOptions, ) -> GeomResult<BooleanOutcome>

Apply one regularized set operation. Read more
Source§

fn solid_requirements(&self) -> SolidRequirements

Admissibility this provider requires of its operands. Read more
Source§

impl Copy for BoolmeshBoolean

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.