Skip to main content

geop_ops/
lib.rs

1//! The elementary structures the kernel's operations work with: parts,
2//! operations, and programs made of operations. It defines what an
3//! operation is, but no operation itself: every operation lives in a
4//! `geop-ops-*` crate of its own, built on this one as a plugin — placing
5//! sketches in `geop-ops-sketch`, reference geometry in `geop-ops-datums`,
6//! extrude and revolve in `geop-ops-extrude-revolve`, booleans in
7//! `geop-ops-booleans`.
8//!
9//! - [`part`]: a complete CAD [`Part`] — a [`geop_core_topology::Model`],
10//!   the sketches and datums used to build it, starting with the frame
11//!   [`ORIGIN`], and a stable name for every entity in it (see
12//!   [Topological naming](#topological-naming)).
13//! - [`operation`]: what an operation is. Built, a step maps a part and
14//!   its arguments to a new part; edited, it shows a
15//!   [`Form`](ui::Form) — fields and visuals — and has its fields set:
16//!
17//!   ```text
18//!   (part, args)                 -> form
19//!   (part, args, field, value)   -> args
20//!   ```
21//!
22//!   The arguments are plain, serializable design data: numbers, choices,
23//!   sketches, and references to entities of the part by name
24//!   ([`EntityRef`]).
25//! - [`ui`]: what an editor exchanges with the operations — the
26//!   [`StepEditEvent`](ui::StepEditEvent)s it sends (a dialog field used, a click or a drag
27//!   as a ray from the eye, a key) and the
28//!   [`Presentation`](ui::Presentation) it gets back — and the
29//!   [`StepEditor`](ui::StepEditor), which makes every operation answer
30//!   them alike: picking entities for a field, dragging a handle, hit tests
31//!   against visuals and against the part as drawn
32//!   ([`PartView`](ui::PartView)). An editor only renders primitives and
33//!   forwards raw input; every decision is made here.
34//! - [`Operations`]: a set of operations a program can use, as one
35//!   serializable enum; `#[derive(Operations)]` writes it. Which operations
36//!   an application offers is its own choice, so the set is defined there,
37//!   not here.
38//! - [`program`]: a [`Program`], an ordered list of steps, each an
39//!   operation with its arguments and an id of its own, that builds a part
40//!   from scratch. A program is design data: it serializes to JSON and
41//!   back without losing anything, and rebuilding the read-back program
42//!   gives the same part, name for name. [`ProgramRunner`] builds it
43//!   incrementally, stopping wherever an editor asks.
44//!
45//! # Parts
46//!
47//! [`Part`] only ever changes through its own methods, each of which forwards
48//! to the identically named `Model` operation and takes the name of every
49//! entity it creates. Its fields are private, so a part can't gain an entity
50//! without a name, or keep the name of one that no longer exists.
51//!
52//! # Topological naming
53//!
54//! A name says *how an entity came to be*, never *when*: it is built only
55//! from inputs that stay the same when a part is rebuilt after an edit
56//! upstream — operation ids, sketch element ids, the names of the entities an
57//! operation consumed, and positions counted along those. Never from an
58//! internal id or the order in which an algorithm happened to create things.
59//! So a program that refers to `extrude(box,end)` keeps meaning the same face
60//! when the box gets taller, and names are stable text that diffs well.
61//!
62//! Every name has the form `kind(operation,arg,...)` (see [`Namer`]):
63//! `kind` is the operation that created the entity, `operation` the id of the
64//! program step that ran it, and the arguments identify the entity within
65//! that step. The operations document their own arguments; for example:
66//!
67//! - `extrude(E)` is the solid extrude step `E` built, `extrude(E,start)` and
68//!   `extrude(E,end)` its caps, `extrude(E,K,c3)` the side face swept by line
69//!   `c3` of sketch `K`, `extrude(E,K,c3,end)` that face's edge on the end cap,
70//!   and `extrude(E,K,p1)` the edge swept by sketch point `p1`.
71//! - `boolean(B,E1,E2,i,n)` is the `i`-th of the `n` points where edges `E1`
72//!   and `E2` (by their names before step `B`) cross, counted along `E1`.
73//!
74//! Operation ids are restricted to [`validate_operation_id`]'s alphabet, so
75//! the arguments of a name — which may themselves be names — can always be
76//! told apart.
77
78// The derives in `geop_ops_derive` name this crate by its path, which has
79// to resolve inside it too.
80extern crate self as geop_ops;
81
82pub mod operation;
83pub mod part;
84pub mod program;
85pub mod ui;
86
87pub use part::{
88    DatumId, EdgeDescription, FaceDescription, NameRegistry, Namer, ORIGIN, Part, PartDescription,
89    PlacedSketch, RefId, SketchId, validate_operation_id,
90};
91
92pub use operation::{EntityRef, Operation, OperationInfo, Operations};
93pub use program::{Program, ProgramRunner, Step, StepResult};
94
95#[doc(hidden)]
96/// What `#[derive(Operations)]` writes refers to, so a crate using it needs
97/// no dependencies of its own for it.
98pub mod __private {
99    pub use geop_core_math::{
100        geop_error::{GeopError, GeopResult},
101        scalars::Scalar,
102    };
103}