1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! `arris` — a B-Rep geometric kernel written from scratch in Rust.
//!
//! This crate is the facade: it re-exports the workspace crates as modules
//! (`arris::math` through `arris::io`) so a consumer depends on one name
//! and reaches everything through it. Nothing lives here that does not
//! live in a lower crate; the guarantees are each crate's
//! (`docs/ARCHITECTURE.md`).
//!
//! ```
//! use arris::math::{Axis, Control, Point3};
//! use arris::topo::Model;
//! use arris::check::{Level, check};
//!
//! let mut m = Model::default();
//! let (cylinder, provenance) =
//! arris::ops::primitive_cylinder(&mut m, Axis::z_at(Point3::origin()), 4.0, 12.0, &Control::NONE)
//! .unwrap();
//! assert!(check(&m, cylinder, Level::Full).is_ok());
//! assert_eq!(provenance.outputs().len(), 10);
//! let text = arris::io::step::write(&m, &[cylinder]).unwrap();
//! assert!(text.starts_with("ISO-10303-21;"));
//!
//! // And back: every solid of a file, each its own result.
//! let mut back = Model::default();
//! let read = arris::io::step::read(&mut back, &text, &Default::default(), &Control::NONE).unwrap();
//! let body = read.solids[0].result.as_ref().unwrap().body;
//! assert!(check(&back, body, Level::Full).is_ok());
//! ```
//!
//! Every operation on a model takes a [`Control`] last, so its caller can
//! stop it: a poll it answers from whatever its platform has (here an
//! `AtomicBool` another thread sets), a budget of steps, both or neither.
//! A stop is `Interrupted` in the operation's own error type, and the
//! model is as it was before the call.
//!
//! ```
//! use arris::{Control, Stop};
//! use arris::ops::{OpError, primitive_box};
//! use arris::topo::Model;
//! use core::sync::atomic::{AtomicBool, Ordering};
//!
//! let mut m = Model::default();
//!
//! // A poll: the consumer's flag, asked at every step.
//! let cancel = AtomicBool::new(true);
//! let poll = || cancel.load(Ordering::Relaxed);
//! let stopped = primitive_box(&mut m, [0.0; 3], [1.0; 3], &Control::poll(&poll));
//! let Err(OpError::Interrupted(stop)) = stopped else { panic!("not stopped") };
//! assert_eq!(stop.by, Stop::Poll);
//! assert!(m.body(arris::topo::BodyId::new(0, 0)).is_err(), "nothing was left in the model");
//!
//! // A budget: the same input and budget stop at the same step everywhere.
//! let spent = primitive_box(&mut m, [0.0; 3], [1.0; 3], &Control::budget(0));
//! assert!(matches!(spent, Err(OpError::Interrupted(s)) if s.by == Stop::Budget && s.steps == 0));
//!
//! // Neither: run to the end. A budget that is enough changes nothing.
//! cancel.store(false, Ordering::Relaxed);
//! assert!(primitive_box(&mut m, [0.0; 3], [1.0; 3], &Control::poll(&poll).with_budget(100)).is_ok());
//! ```
pub use ;
pub use arris_check as check;
pub use arris_geom as geom;
pub use arris_io as io;
pub use arris_math as math;
pub use arris_mesh as mesh;
pub use arris_ops as ops;
pub use arris_topo as topo;