Skip to main content

geop_core_editor/view/
mod.rs

1//! [`PartView`]: a part as the viewport draws it, and picking elements of
2//! it with a [`Pointer`].
3//!
4//! A part is drawn from its rasterization — sampled edges, triangulated
5//! faces, outlined sketches — and a pick tests against exactly that, never
6//! re-deriving geometry of its own, so a pick cannot disagree with what is
7//! on screen. The same goes for what the viewer draws besides the part: the
8//! datums are laid out here, by the sizes the viewer draws them with, and
9//! picked by the same rules.
10//!
11//! Each crate draws its own targets into a view: the model its vertices,
12//! edges and faces, the sketches theirs, the datums theirs; an editor
13//! composes them. A pick names what it hits as the crate that drew it named
14//! it ([`PickedElement`]) and by the kind of thing drawn ([`drawn`]), which
15//! the crate defining an element turns into one ([`crate::selectable`]).
16//!
17//! The parts placed in a part are drawn by reference: each placed part —
18//! however deep — is listed once, with where it is ([`ViewInstance`]), and
19//! drawn from its component's own view, built once and shared by every
20//! instance of it. Moving a placed part changes where it is, not what is
21//! drawn. A pick moves the pointer into each placed part's own frame and
22//! names what it hits as that part names it, its target behind the
23//! instance's path ([`Located`]): `/bolt:model`.
24
25pub mod icons;
26pub mod kept;
27pub mod lit;
28pub mod picture;
29#[cfg(test)]
30mod tests;
31mod tree;
32
33use std::{cell::RefCell, collections::BTreeMap, rc::Rc};
34
35use crate::editing::{
36    Extent, Pointer,
37    hit::{ElementHit, Scene, cycled, nearer},
38};
39use geop_core_math::{
40    geop_error::GeopResult,
41    polygon::polygons_contain,
42    primitives::{CoordinateSystem, DatumComponent, DatumKind, FrameAxis, Motion, Pose, Ray},
43    scalars::Scalar,
44    vector::{Vector2, Vector3},
45};
46use geop_core_program::{
47    element::{ElementReference, HasElements, Kind, PickedElement, whole},
48    placed::{INSTANCE_SEPARATOR, Located},
49    reader::Reader,
50    target::{Target, TargetReference},
51};
52use serde::Serialize;
53use tree::FaceTree;
54pub use tree::triangles_tested;
55
56/// The kinds of what a view draws, as a pick names them
57/// ([`PickedElement::kind`]).
58pub mod drawn {
59    /// A vertex of the model.
60    pub const VERTEX: &str = "vertex";
61    /// An edge of the model.
62    pub const EDGE: &str = "edge";
63    /// A face of the model.
64    pub const FACE: &str = "face";
65    /// A sketch, hit inside one of its regions or near one of its curves.
66    pub const SKETCH: &str = "sketch";
67    /// A point of a sketch.
68    pub const SKETCH_POINT: &str = "sketch_point";
69    /// A curve of a sketch.
70    pub const SKETCH_CURVE: &str = "sketch_curve";
71    /// A datum, or a component of a frame datum.
72    pub const DATUM: &str = "datum";
73    /// A frame put on what is picked — a face, an edge, a point, a datum —
74    /// at the corner or side of a face, or the end of an edge, the pointer
75    /// is near (see [`super::FramePick`]).
76    pub const FRAME: &str = "frame";
77}
78
79/// How near an end of an edge a pick for a frame is taken to be at it: that
80/// part of its length from it.
81const END_OF_AN_EDGE: f64 = 0.2;
82
83/// How near a corner of a face, in reaches of the pointer, a pick for a
84/// frame on it is taken to be at it, and how near a side: the corner first.
85const NEAR_CORNER: f64 = 4.0;
86const NEAR_SIDE: f64 = 3.0;
87
88/// A frame picked (see [`drawn::FRAME`]): what it is put on, and what of
89/// that it sits at — a corner or a side of a face, an end of an edge —
90/// each as a pick names it, of one target. Picked as one element of the
91/// kind [`drawn::FRAME`], named `on_kind/on_name`, or
92/// `on_kind/on_name|at_kind/at_name`: no name has a `/` or a `|`.
93#[derive(Clone, Debug, PartialEq)]
94pub struct FramePick {
95    pub on: PickedElement,
96    pub at: Option<PickedElement>,
97}
98
99impl FramePick {
100    /// It as one element picked.
101    pub fn picked(&self) -> PickedElement {
102        let named = |p: &PickedElement| format!("{}/{}", p.kind, p.name);
103        let name = match &self.at {
104            None => named(&self.on),
105            Some(at) => format!("{}|{}", named(&self.on), named(at)),
106        };
107        PickedElement {
108            target: self.on.target.clone(),
109            kind: drawn::FRAME.to_string(),
110            name,
111        }
112    }
113
114    /// The frame `picked` names, if it names one.
115    pub fn of(picked: &PickedElement) -> Option<Self> {
116        (picked.kind == drawn::FRAME).then_some(())?;
117        let element = |text: &str| {
118            let (kind, name) = text.split_once('/')?;
119            Some(PickedElement {
120                target: picked.target.clone(),
121                kind: kind.to_string(),
122                name: name.to_string(),
123            })
124        };
125        let (on, at) = match picked.name.split_once('|') {
126            Some((on, at)) => (on, Some(element(at)?)),
127            None => (picked.name.as_str(), None),
128        };
129        Some(Self {
130            on: element(on)?,
131            at,
132        })
133    }
134}
135
136/// Samples per edge and per parametric direction of a face. A face's grid
137/// is refined further where its own curvature asks for it, so this is the
138/// floor, not the ceiling.
139pub const RESOLUTION: usize = 24;
140
141/// How long a frame datum's axes are, in reaches: it is drawn at a constant
142/// size on screen, with its origin ball, its axes and the squares of its
143/// planes laid out in fractions of that, in [`PartView::pick`] as in the
144/// viewer.
145pub const FRAME: f64 = 10.0;
146
147/// How big an empty part's drawing is: what a viewer frames, and its datum
148/// planes' size, before anything is drawn. Lengths are millimetres, and
149/// the parts of a robot are 10 to 500 mm.
150pub const EMPTY_EXTENT: f64 = 100.0;
151
152/// A vertex of the part, as drawn.
153#[derive(Clone, Debug, Serialize)]
154pub struct ViewVertex {
155    pub name: String,
156    /// The solid it is a corner of.
157    pub solid: Option<String>,
158    /// The faces it is a corner of. Of no solid, it is hidden with all of
159    /// them; a face hit does not hide it (see [`PartView::pick`]).
160    pub faces: Vec<String>,
161    pub at: Vector3,
162}
163
164/// An edge of the part, as drawn: its curve sampled into a polyline.
165#[derive(Clone, Debug, Serialize)]
166pub struct ViewEdge {
167    pub name: String,
168    /// The solid it bounds.
169    pub solid: Option<String>,
170    /// The faces it bounds. Of no solid, it is hidden with all of them; a
171    /// face hit does not hide it (see [`PartView::pick`]).
172    pub faces: Vec<String>,
173    pub polyline: Vec<Vector3>,
174    /// Whether it lies within one smooth surface, its two faces pieces of it:
175    /// a cylinder's seam between its quarters, not where a fillet leaves a
176    /// face. A viewer draws no line for it, until it is lit. It can still be
177    /// pointed at and picked like any other.
178    pub within_a_surface: bool,
179    /// The vertices it runs between, by name.
180    #[serde(skip)]
181    pub ends: [String; 2],
182}
183
184/// A face of the part, as drawn: its name, and its triangles. Serialized,
185/// the triangles are named by their key ([`FaceMesh::key`]): a viewer is
186/// sent each mesh once ([`crate::editor::SceneState::meshes`]).
187#[derive(Clone, Debug, Serialize)]
188pub struct ViewFace {
189    pub name: String,
190    /// What else it answers to: the names of faces made one with it, which
191    /// what was given by name, a colour, still means.
192    #[serde(skip_serializing_if = "Vec::is_empty")]
193    pub also: Vec<String>,
194    /// The solid the face bounds.
195    pub solid: Option<String>,
196    /// The step whose feature made it, if one did.
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub feature: Option<String>,
199    #[serde(serialize_with = "FaceMesh::serialize_key")]
200    pub mesh: Rc<FaceMesh>,
201}
202
203/// A face triangulated, with the surface's normal at each corner, and what
204/// it is known by: its key, a hash of what a viewer is sent of it — so a
205/// face drawn alike, in this part or another, is one mesh to a viewer.
206///
207/// Its corners and normals are sharp: a mesh is a polygon drawn near the
208/// face, and which point of a corner's enclosure it is drawn through is a
209/// free choice — the middle — which a viewer is sent and a pick tests.
210///
211/// A viewer is sent it as a viewer draws it: each corner its triangles
212/// share once, and each triangle by its corners' indices — in base64, the
213/// corners' points and normals as 32-bit floats, `x y z` after one
214/// another, the indices as 32-bit integers, three a triangle, all little
215/// endian: `{"positions", "normals", "indices"}`. A tenth of a mesh's size
216/// written as numbers.
217#[derive(Debug)]
218pub struct FaceMesh {
219    pub key: String,
220    pub triangles: Vec<[Vector3; 3]>,
221    pub normals: Vec<[Vector3; 3]>,
222}
223
224impl Serialize for FaceMesh {
225    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
226        use serde::ser::SerializeStruct;
227        let mut index: std::collections::HashMap<[u32; 6], u32> = Default::default();
228        let (mut positions, mut normals, mut indices) = (Vec::new(), Vec::new(), Vec::new());
229        for (points, at) in self.triangles.iter().zip(&self.normals) {
230            for (p, n) in points.iter().zip(at) {
231                let p = p.to_array().map(|x| x.to_f64() as f32);
232                let n = n.to_array().map(|x| x.to_f64() as f32);
233                let bits = [p[0], p[1], p[2], n[0], n[1], n[2]].map(f32::to_bits);
234                let next = index.len() as u32;
235                let corner = *index.entry(bits).or_insert_with(|| {
236                    positions.extend(p.iter().flat_map(|x| x.to_le_bytes()));
237                    normals.extend(n.iter().flat_map(|x| x.to_le_bytes()));
238                    next
239                });
240                indices.extend(corner.to_le_bytes());
241            }
242        }
243        let base64 = geop_core_program::workspace::base64;
244        let mut s = serializer.serialize_struct("FaceMesh", 3)?;
245        s.serialize_field("positions", &base64(&positions))?;
246        s.serialize_field("normals", &base64(&normals))?;
247        s.serialize_field("indices", &base64(&indices))?;
248        s.end()
249    }
250}
251
252impl FaceMesh {
253    /// The mesh of `triangles`, each with the normals `normals` at its
254    /// corners, each taken at the middle of its enclosure.
255    pub fn new(triangles: Vec<[Vector3; 3]>, normals: Vec<[Vector3; 3]>) -> Rc<Self> {
256        use std::hash::{Hash, Hasher};
257        FACES_DRAWN.set(FACES_DRAWN.get() + 1);
258        let sharp = |corners: Vec<[Vector3; 3]>| -> Vec<[Vector3; 3]> {
259            (corners.into_iter())
260                .map(|corner| corner.map(|p| p.map(|x| Scalar::from_f64(x.to_f64()))))
261                .collect()
262        };
263        let (triangles, normals) = (sharp(triangles), sharp(normals));
264        let mut key = std::hash::DefaultHasher::new();
265        for p in triangles.iter().chain(&normals).flatten() {
266            for x in p.to_array() {
267                x.to_f64().to_bits().hash(&mut key);
268            }
269        }
270        triangles.len().hash(&mut key);
271        Rc::new(Self {
272            key: format!("{:016x}", key.finish()),
273            triangles,
274            normals,
275        })
276    }
277
278    /// Serializes `mesh` as its key.
279    fn serialize_key<S: serde::Serializer>(mesh: &Rc<Self>, s: S) -> Result<S::Ok, S::Error> {
280        s.serialize_str(&mesh.key)
281    }
282}
283
284/// A curve of a sketch, as drawn, in the sketch's plane, by the name its
285/// sketch gives it.
286#[derive(Clone, Debug, Serialize)]
287pub struct ViewCurve {
288    pub id: String,
289    pub construction: bool,
290    pub polyline: Vec<Vector2>,
291}
292
293/// A point of a sketch, as drawn, in the sketch's plane, by the name its
294/// sketch gives it.
295#[derive(Clone, Debug, Serialize)]
296pub struct ViewSketchPoint {
297    pub id: String,
298    pub at: Vector2,
299}
300
301/// A sketch of the part, as drawn: its plane, its closed regions (each an
302/// outer loop and its holes), its curves and its points, in the plane's
303/// `u`/`v` coordinates.
304#[derive(Clone, Debug, Serialize)]
305pub struct ViewSketch {
306    pub name: String,
307    /// The target it is, which a pick of it or its elements names.
308    pub target: String,
309    pub plane: CoordinateSystem,
310    #[serde(skip)]
311    pub regions: Vec<Vec<Vec<Vector2>>>,
312    pub curves: Vec<ViewCurve>,
313    pub points: Vec<ViewSketchPoint>,
314}
315
316/// A datum of the part. A frame's axes and planes are picked on their own,
317/// by the names its target gives them ([`ViewDatum::components`]).
318#[derive(Clone, Debug, Serialize)]
319pub struct ViewDatum {
320    pub name: String,
321    pub kind: DatumKind,
322    pub frame: CoordinateSystem,
323    /// The names of a frame's components, as its target names them.
324    #[serde(skip)]
325    pub components: Vec<(DatumComponent, String)>,
326}
327
328/// Something drawn on the part besides its topology — a cosmetic thread —
329/// and what it is called.
330#[derive(Clone, Debug, PartialEq, Serialize)]
331pub struct ViewAnnotation {
332    pub name: String,
333    pub label: String,
334    pub polyline: Vec<Vector3>,
335}
336
337/// What a step draws on the part besides its topology — cosmetic threads —
338/// the value of its target [`annotations`].
339#[derive(Clone, Debug, Default, PartialEq)]
340pub struct Annotations(pub Vec<ViewAnnotation>);
341
342/// What the step `step` draws on the part: defined by a step that draws
343/// something, and drawn for every step that does ([`annotations_of`]).
344pub fn annotations(step: &str) -> TargetReference<Annotations> {
345    TargetReference::new(format!("annotations:{step}"))
346}
347
348/// Everything the steps `reader` sees draw on the part, step by step.
349pub fn annotations_of(reader: &Reader) -> Vec<ViewAnnotation> {
350    (reader.targets_of::<Annotations>().into_iter())
351        .filter_map(|target| {
352            let whole = ElementReference::<Annotations, Annotations>::whole(target);
353            reader
354                .retrieve_element(&whole)
355                .ok()
356                .map(|drawn| drawn.0.clone())
357        })
358        .flatten()
359        .collect()
360}
361
362/// Each step's own.
363impl Target for Annotations {}
364
365/// Read whole.
366impl Kind for Annotations {
367    const NAME: &'static str = "annotations";
368}
369
370impl HasElements<Annotations> for Annotations {
371    type Element<'a> = &'a Annotations;
372
373    fn element(&self, name: &str) -> GeopResult<&Annotations> {
374        whole(self, name)
375    }
376
377    fn names_target(name: &str) -> bool {
378        name.starts_with("annotations:")
379    }
380}
381
382/// An entry of the part's structure a step adds beside what every part has:
383/// a mate, of kind `mate`.
384#[derive(Clone, Debug, PartialEq, Serialize)]
385pub struct Listed {
386    /// What it is — the group a structure tree lists it in: `mate`.
387    pub kind: String,
388    pub name: String,
389    /// What it refers to: the elements a mate is between, lit while it is
390    /// pointed at.
391    pub elements: Vec<PickedElement>,
392}
393
394/// The entries of the part's structure a step adds: the value of its target
395/// [`listing`].
396#[derive(Clone, Debug, Default, PartialEq)]
397pub struct Listing(pub Vec<Listed>);
398
399/// The entries of the part's structure the step `step` adds.
400pub fn listing(step: &str) -> TargetReference<Listing> {
401    TargetReference::new(format!("listing:{step}"))
402}
403
404/// Every entry the steps `reader` sees add to the structure, step by step.
405pub fn listed_by_steps(reader: &Reader) -> Vec<Listed> {
406    (reader.targets_of::<Listing>().into_iter())
407        .filter_map(|target| {
408            let whole = ElementReference::<Listing, Listing>::whole(target);
409            reader
410                .retrieve_element(&whole)
411                .ok()
412                .map(|listing| listing.0.clone())
413        })
414        .flatten()
415        .collect()
416}
417
418/// Each step's own.
419impl Target for Listing {}
420
421/// Read whole.
422impl Kind for Listing {
423    const NAME: &'static str = "listing";
424}
425
426impl HasElements<Listing> for Listing {
427    type Element<'a> = &'a Listing;
428
429    fn element(&self, name: &str) -> GeopResult<&Listing> {
430        whole(self, name)
431    }
432
433    fn names_target(name: &str) -> bool {
434        name.starts_with("listing:")
435    }
436}
437
438/// A part placed in the part drawn — directly or in a part placed in it —
439/// drawn as its part's own view moved to where it is. Serialized, a viewer
440/// gets the part by its key and where to draw it.
441#[derive(Clone, Serialize)]
442pub struct ViewInstance {
443    /// Its name in the part drawn: `bolt`, or `asm/bolt` for one placed in
444    /// a placed part.
445    pub name: String,
446    /// The key of its part.
447    pub component: String,
448    /// Where it is: its own frame in the part drawn.
449    pub frame: CoordinateSystem,
450    #[serde(skip)]
451    pub pose: Pose,
452    /// Its part as drawn.
453    #[serde(skip)]
454    pub view: Rc<PartView>,
455    /// The state of the part drawn its pose is — `None` for a copy of a
456    /// pattern, which goes where the pattern puts it.
457    #[serde(skip)]
458    pub state: Option<String>,
459    /// Whether no mate moves it.
460    #[serde(skip)]
461    pub fixed: bool,
462    /// The colour it is drawn in over its own, `#rrggbb`, if the user chose
463    /// one for it (see [`crate::editor::Command::Appearance`]).
464    #[serde(skip_serializing_if = "Option::is_none")]
465    pub color: Option<String>,
466}
467
468impl std::fmt::Debug for ViewInstance {
469    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470        write!(
471            f,
472            "ViewInstance({}, {}, {:?})",
473            self.name, self.component, self.pose
474        )
475    }
476}
477
478/// A part as the viewport draws it, every element by name — and, serialized,
479/// what a viewer draws. Each crate draws its own targets into it; then
480/// [`PartView::finish`] measures it.
481#[derive(Clone, Debug, Serialize)]
482pub struct PartView {
483    /// The target its vertices, edges and faces are of: what a viewer
484    /// matches an element's target with to light it.
485    pub model: String,
486    pub vertices: Vec<ViewVertex>,
487    pub edges: Vec<ViewEdge>,
488    pub faces: Vec<ViewFace>,
489    pub sketches: Vec<ViewSketch>,
490    /// The target its datums are of.
491    pub datum_target: String,
492    pub datums: Vec<ViewDatum>,
493    /// What its steps draw on it besides its topology: cosmetic threads.
494    pub annotations: Vec<ViewAnnotation>,
495    /// The part's solids, oldest first.
496    pub solids: Vec<String>,
497    /// Every part placed in it, and in those, however deep. Not
498    /// serialized: a viewer is sent them apart, as they change, by name.
499    #[serde(skip)]
500    pub instances: Vec<ViewInstance>,
501    /// Where the drawing is and how big: the center and diagonal, at least
502    /// one, of the box around it — for an empty part, [`EMPTY_EXTENT`]
503    /// around the origin. Datum planes and axes, which are endless, are
504    /// drawn this big around the point of them nearest the center.
505    pub extent: Extent,
506    /// The part's colour, `#rrggbb`; none for the viewer's own.
507    pub color: Option<String>,
508    /// The colours of its faces drawn in one of their own, `#rrggbb`, by the
509    /// face's name: over [`Self::color`], and under a colour its instance
510    /// is drawn in ([`ViewInstance::color`]). Asked by name, so a name no
511    /// face has now is simply never asked for, and drawing them reads
512    /// nothing of the faces.
513    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
514    pub face_colors: BTreeMap<String, String>,
515    /// The tree of its faces' triangles a pick tests the ray against (see
516    /// [`tree`]): built when it is first picked in, and again only for
517    /// other faces.
518    #[serde(skip)]
519    faces_tree: RefCell<Option<Rc<FaceTree>>>,
520}
521
522/// One part of what a pick tests: the part drawn itself, or a placed part,
523/// with the pointer moved into its own frame.
524struct Layer<'v> {
525    view: &'v PartView,
526    pointer: Pointer,
527    /// Whether the pointer comes near enough the box around its view
528    /// ([`PartView::extent`]) to hit any of its vertices, edges or faces:
529    /// only its datums can be hit otherwise — a frame is drawn at a size of
530    /// its own, a plane or an axis as large as the whole drawing.
531    near: bool,
532    /// Where it is, and back; `None` for the part drawn itself.
533    motion: Option<(Motion, Motion)>,
534    /// The instance's name, for a placed part.
535    instance: Option<&'v str>,
536    /// What the viewer does not draw, of the whole drawing.
537    hidden: &'v [String],
538}
539
540impl Layer<'_> {
541    /// Whether the viewer does not draw what this layer names `name`: a
542    /// solid, a face of none, a sketch, a datum — by its key in the part
543    /// drawn (see [`Located::key`]).
544    fn hides(&self, name: &str) -> bool {
545        let key = Located::in_instance(self.instance.unwrap_or_default(), name).key();
546        self.hidden.binary_search(&key).is_ok()
547    }
548
549    /// Whether the face `face` is drawn: its solid is not hidden, or, of
550    /// none, it is not.
551    fn shows_face(&self, face: &ViewFace) -> bool {
552        match &face.solid {
553            Some(solid) => !self.hides(solid),
554            None => !self.hides(&face.name),
555        }
556    }
557
558    /// Whether a vertex or an edge of the solid `solid`, bounding `faces`,
559    /// is drawn: its solid is not hidden, or, of none, not every face it
560    /// bounds is.
561    fn shows_boundary(&self, solid: &Option<String>, faces: &[String]) -> bool {
562        match solid {
563            Some(solid) => !self.hides(solid),
564            None => faces.is_empty() || faces.iter().any(|f| !self.hides(f)),
565        }
566    }
567
568    /// The nearest face drawn the ray enters.
569    fn pick_face(&self) -> Option<(Scalar, &ViewFace)> {
570        (self.view).pick_face(&self.pointer, |f| self.shows_face(f))
571    }
572
573    /// Every face drawn the ray enters, the nearest first.
574    fn faces_entered(&self) -> Vec<(Scalar, &ViewFace)> {
575        (self.view).faces_entered(&self.pointer, |f| self.shows_face(f))
576    }
577
578    /// The element `kind` `name` of the target `target` of this layer, as
579    /// the part drawn names it.
580    fn element(&self, target: &str, kind: &str, name: &str) -> PickedElement {
581        PickedElement {
582            target: Located::in_instance(self.instance.unwrap_or_default(), target),
583            kind: kind.to_string(),
584            name: name.to_string(),
585        }
586    }
587
588    /// The point `p` of this layer where the part drawn has it.
589    fn world(&self, p: Vector3) -> Vector3 {
590        match &self.motion {
591            Some((there, _)) => there.apply(&p),
592            None => p,
593        }
594    }
595
596    /// The point `p` of the part drawn in this layer's own frame.
597    fn local(&self, p: Vector3) -> Vector3 {
598        match &self.motion {
599            Some((_, back)) => back.apply(&p),
600            None => p,
601        }
602    }
603
604    /// The element `kind` `name` of `target`, hit at `point`, `t` along the
605    /// ray, as a hit of the part drawn.
606    fn hit(&self, target: &str, kind: &str, name: &str, point: Vector3, t: Scalar) -> ElementHit {
607        ElementHit {
608            element: self.element(target, kind, name),
609            point: self.world(point),
610            t,
611        }
612    }
613}
614
615impl PartView {
616    /// The colour of its own `face` has, if one was given: by its name, or by
617    /// what else it answers to.
618    pub fn color_of_face(&self, face: &ViewFace) -> Option<&String> {
619        (std::iter::once(&face.name).chain(&face.also)).find_map(|name| self.face_colors.get(name))
620    }
621
622    /// Nothing drawn, reaching as far as `extent`: what a viewer is sent
623    /// while a step is edited on a sheet of its own, which it frames.
624    pub fn blank(extent: Extent) -> Self {
625        Self {
626            model: String::new(),
627            vertices: Vec::new(),
628            edges: Vec::new(),
629            faces: Vec::new(),
630            sketches: Vec::new(),
631            datum_target: String::new(),
632            datums: Vec::new(),
633            annotations: Vec::new(),
634            solids: Vec::new(),
635            instances: Vec::new(),
636            extent,
637            color: None,
638            face_colors: BTreeMap::new(),
639            faces_tree: RefCell::default(),
640        }
641    }
642
643    /// Nothing drawn yet, to be drawn into: as big as an empty part.
644    pub fn new() -> Self {
645        Self::blank(Extent {
646            center: Vector3::zero(),
647            size: Scalar::from_f64(EMPTY_EXTENT),
648        })
649    }
650
651    /// What `drawn` drew added: what one drawer drew of a part, into what
652    /// the others drew of it (see [`crate::registry::Drawings`]). Drawers
653    /// draw what is theirs alone, so nothing is drawn twice.
654    pub fn add(&mut self, drawn: &PartView) {
655        if !drawn.model.is_empty() {
656            self.model.clone_from(&drawn.model);
657        }
658        if !drawn.datum_target.is_empty() {
659            self.datum_target.clone_from(&drawn.datum_target);
660        }
661        if drawn.color.is_some() {
662            self.color.clone_from(&drawn.color);
663        }
664        (self.face_colors).extend(
665            drawn
666                .face_colors
667                .iter()
668                .map(|(k, v)| (k.clone(), v.clone())),
669        );
670        self.vertices.extend_from_slice(&drawn.vertices);
671        self.edges.extend_from_slice(&drawn.edges);
672        self.faces.extend_from_slice(&drawn.faces);
673        self.sketches.extend_from_slice(&drawn.sketches);
674        self.datums.extend_from_slice(&drawn.datums);
675        self.annotations.extend_from_slice(&drawn.annotations);
676        self.solids.extend_from_slice(&drawn.solids);
677        self.instances.extend_from_slice(&drawn.instances);
678    }
679
680    /// Done drawing: measured.
681    pub fn finish(mut self) -> Self {
682        PARTS_DRAWN.set(PARTS_DRAWN.get() + 1);
683        self.extent = self.measure();
684        self
685    }
686
687    /// Whether `pointer` could hit any of its vertices, edges or faces —
688    /// within one reach of them, as a pick asks: whether it passes within
689    /// one reach of the ball around the box of everything drawn
690    /// ([`Extent`]), the reach taken where the ball ends furthest along
691    /// the ray. A pick tests every triangle of a part it comes near, so for
692    /// a part placed hundreds of times, this is what it can skip.
693    fn near(&self, pointer: &Pointer) -> bool {
694        let Ok(radius) = self.extent.size.div(Scalar::TWO) else {
695            return true;
696        };
697        let (dist, t) = pointer.ray.distance_to_point(&self.extent.center);
698        !dist
699            .sub(radius)
700            .definitely_greater(pointer.reach_at(1.0, t.add(radius)))
701    }
702
703    /// The part drawn itself, then every placed part drawn — not hidden,
704    /// nor placed in one hidden — each with `pointer` moved into its frame;
705    /// of each, only what `hidden` does not name is hit.
706    fn layers<'v>(&'v self, pointer: &Pointer, hidden: &'v [String]) -> Vec<Layer<'v>> {
707        let mut layers = vec![Layer {
708            view: self,
709            pointer: *pointer,
710            near: true,
711            motion: None,
712            instance: None,
713            hidden,
714        }];
715        let instance_hidden = |name: &str| {
716            let mut path = name;
717            loop {
718                if hidden.binary_search_by(|h| h.as_str().cmp(path)).is_ok() {
719                    return true;
720                }
721                match path.rsplit_once(INSTANCE_SEPARATOR) {
722                    Some((outer, _)) => path = outer,
723                    None => return false,
724                }
725            }
726        };
727        for instance in self.instances.iter().filter(|i| !instance_hidden(&i.name)) {
728            let back = instance.pose.inverse().motion();
729            let ray = &pointer.ray;
730            let Ok(ray) = Ray::try_new(back.apply(ray.origin()), back.rotate(ray.dir())) else {
731                continue;
732            };
733            let view = &*instance.view;
734            let pointer = Pointer {
735                cycle: pointer.cycle,
736                ray,
737                reach: pointer.reach,
738            };
739            layers.push(Layer {
740                near: view.near(&pointer),
741                view,
742                pointer,
743                motion: Some((instance.pose.motion(), back)),
744                instance: Some(&instance.name),
745                hidden,
746            });
747        }
748        layers
749    }
750
751    /// The placed part a drag at `pointer` moves, and how far along the ray
752    /// it is hit: the one whose face the ray enters first — or, for a part
753    /// placed in one placed rigid, the innermost one around it whose pose is
754    /// a state of the part drawn and not fixed: what moves it. A part fixed
755    /// in a sub-assembly moves with the sub-assembly, so a drag of it moves
756    /// that. None where every part around it is fixed: no drag moves it.
757    pub fn part_to_drag(
758        &self,
759        pointer: &Pointer,
760        hidden: &[String],
761    ) -> Option<(&ViewInstance, Scalar)> {
762        let layers = self.layers(pointer, hidden);
763        // The part's own faces hide what is behind them too.
764        let (t, hit) = layers
765            .iter()
766            .filter(|l| l.near)
767            .filter_map(|l| Some((l.pick_face()?.0, l.instance)))
768            .min_by(|a, b| nearer(a.0, b.0))?;
769        let hit = hit?;
770        let moved = self
771            .instances
772            .iter()
773            .filter(|i| i.state.is_some() && !i.fixed)
774            .filter(|i| {
775                i.name == hit
776                    || (hit.strip_prefix(&i.name))
777                        .is_some_and(|r| r.starts_with(INSTANCE_SEPARATOR))
778            })
779            .max_by_key(|i| i.name.len())?;
780        Some((moved, t))
781    }
782
783    /// How far along `pointer`'s ray it first enters the placed part
784    /// `instance`, if it does and is drawn.
785    pub fn pick_instance(
786        &self,
787        instance: &str,
788        pointer: &Pointer,
789        hidden: &[String],
790    ) -> Option<Scalar> {
791        let layers = self.layers(pointer, hidden);
792        let layer = layers.iter().find(|l| l.instance == Some(instance))?;
793        layer.near.then(|| layer.pick_face())?.map(|(t, _)| t)
794    }
795
796    /// The box around what it draws itself — its vertices, edges, faces
797    /// and sketches, not the parts placed in it — if it draws anything.
798    fn own_box(&self) -> Option<Vector3> {
799        let sketch_points = self.sketches.iter().flat_map(|sketch| {
800            (sketch.curves.iter())
801                .flat_map(|c| &c.polyline)
802                .map(|p| sketch.plane.uv_to_xyz(p))
803        });
804        (self.vertices.iter())
805            .map(|v| v.at)
806            .chain(self.edges.iter().flat_map(|e| e.polyline.iter().copied()))
807            .chain((self.faces.iter()).flat_map(|f| f.mesh.triangles.iter().flatten().copied()))
808            .chain(sketch_points)
809            .reduce(|a, b| a.union(&b))
810    }
811
812    /// The box around everything drawn: the union of every point of it,
813    /// and of the corners of every placed part's own box, where it is.
814    fn measure(&self) -> Extent {
815        // Each placed part by the corners of its own box, where it is: the
816        // box around what it draws, not a cube as wide as that box's
817        // diagonal, which framed an assembly far too small.
818        let mut corners = Vec::new();
819        for instance in &self.instances {
820            let Some(own) = instance.view.own_box() else {
821                continue;
822            };
823            let motion = instance.pose.motion();
824            for i in 0..8 {
825                let corner = Vector3::from_array([0, 1, 2].map(|k| match i >> k & 1 {
826                    0 => own[k].lower(),
827                    _ => own[k].upper(),
828                }));
829                corners.push(motion.apply(&corner));
830            }
831        }
832        let hull = self.own_box().into_iter();
833        let hull = hull.into_iter().chain(corners).reduce(|a, b| a.union(&b));
834        let Some(hull) = hull else {
835            return Extent {
836                center: Vector3::zero(),
837                size: Scalar::from_f64(EMPTY_EXTENT),
838            };
839        };
840        let size = Vector3::from_array([0, 1, 2].map(|k| hull[k].width())).norm();
841        Extent {
842            center: Vector3::from_array([0, 1, 2].map(|k| hull[k].midpoint())),
843            size: if size.definitely_less(Scalar::ONE) {
844                Scalar::ONE
845            } else {
846                size
847            },
848        }
849    }
850
851    /// Every element drawn of a kind in `accepts` under the pointer, each
852    /// once (see [`Scene::under`]). The first is the one meant at a glance.
853    /// Frame datums are drawn on top of everything, so they come first.
854    /// Otherwise a vertex or a sketch point, else an edge or a sketch curve,
855    /// near the pointer — and not hidden behind a face — comes first: the
856    /// smallest element under the pointer is the one meant. Else the
857    /// nearest along the ray of the faces, sketches and other datums hit.
858    /// Everything else under the pointer follows, front to back along the
859    /// ray: the faces behind the first, and the vertices and edges they
860    /// hide. The parts placed in the part count alike, each where it is
861    /// (see [`PartView::layers`]): a vertex of one is hidden behind a face
862    /// of another. What the viewer does not draw — named in `hidden`,
863    /// sorted, as [`crate::editor::SceneState::hidden`] names it — is not
864    /// hit, and hides nothing behind it: a pick is made in what is seen.
865    pub fn under(
866        &self,
867        pointer: &Pointer,
868        accepts: &[String],
869        hidden: &[String],
870    ) -> Vec<ElementHit> {
871        let accepted = |kind: &str| accepts.iter().any(|a| a == kind);
872        if accepted(drawn::FRAME) {
873            return self.frames_under(pointer, hidden);
874        }
875        let layers = self.layers(pointer, hidden);
876        // What comes first, and everything under the pointer.
877        let mut first = None;
878        let mut all = Vec::new();
879        if accepted(drawn::DATUM) {
880            let [balls, axes, planes] = (layers.iter()).map(|l| l.view.frame_parts_under(l)).fold(
881                Default::default(),
882                |mut parts: [Vec<_>; 3], of| {
883                    for (part, hits) in parts.iter_mut().zip(of) {
884                        part.extend(hits);
885                    }
886                    parts
887                },
888            );
889            first = (nearest(balls.iter().cloned()))
890                .or_else(|| nearest(axes.iter().cloned()))
891                .or_else(|| nearest(planes.iter().cloned()));
892            all.extend(balls.into_iter().chain(axes).chain(planes));
893        }
894
895        // Every face of every layer the ray enters, the nearest first: a
896        // rigid motion keeps distances along the ray, so every layer's `t`
897        // is the part drawn's.
898        let mut faces: Vec<_> = (layers.iter())
899            .filter(|l| l.near)
900            .flat_map(|l| l.faces_entered().into_iter().map(move |(t, f)| (t, l, f)))
901            .collect();
902        faces.sort_by(|a, b| nearer(a.0, b.0));
903        let face = faces.first();
904        // In front of the face hit, give or take the reach — or on its
905        // boundary, of the same layer: `faces`, those a vertex or an edge
906        // bounds, name it. That is asked of the topology, not the depth: at
907        // a glancing look, an edge of the face hit lies further along the
908        // ray than the face is hit by more than a reach, and its triangles
909        // are chords, in front of a face that curves away.
910        let visible = |t: Scalar, faces: &[String], layer: &Layer<'_>| {
911            face.is_none_or(|(ft, l, f)| {
912                (l.instance == layer.instance && faces.contains(&f.name))
913                    || !t.definitely_greater(ft.add(pointer.reach_at(1.0, *ft)))
914            })
915        };
916
917        // Points and curves near the pointer, each with whether it is seen.
918        let mut points = Vec::new();
919        for l in layers.iter().filter(|l| l.near) {
920            let ray = &l.pointer.ray;
921            let near = |at: &Vector3, faces: &[String]| {
922                let (dist, t) = ray.distance_to_point(at);
923                (l.pointer.within(dist, t, 1.0)).then(|| (t, visible(t, faces, l)))
924            };
925            if accepted(drawn::VERTEX) {
926                for v in (l.view.vertices.iter()).filter(|v| l.shows_boundary(&v.solid, &v.faces)) {
927                    if let Some((t, seen)) = near(&v.at, &v.faces) {
928                        points.push((l.hit(&l.view.model, drawn::VERTEX, &v.name, v.at, t), seen));
929                    }
930                }
931            }
932            if accepted(drawn::SKETCH_POINT) {
933                for sketch in l.view.sketches.iter().filter(|s| !l.hides(&s.name)) {
934                    for p in &sketch.points {
935                        let at = sketch.plane.uv_to_xyz(&p.at);
936                        if let Some((t, seen)) = near(&at, &[]) {
937                            let hit = l.hit(&sketch.target, drawn::SKETCH_POINT, &p.id, at, t);
938                            points.push((hit, seen));
939                        }
940                    }
941                }
942            }
943        }
944        let (mut edges, mut sketch_curves) = (Vec::new(), Vec::new());
945        for l in layers.iter().filter(|l| l.near) {
946            let ray = &l.pointer.ray;
947            // How far along the ray `polyline` is first hit, if it is near
948            // enough — where it is seen, if it is anywhere — and whether
949            // it is seen there.
950            let hit_along = |polyline: &mut dyn Iterator<Item = (Vector3, Vector3)>,
951                             faces: &[String]| {
952                polyline
953                    .map(|(a, b)| ray.distance_to_segment(&a, &b))
954                    .filter(|&(dist, t)| l.pointer.within(dist, t, 1.0))
955                    .map(|(_, t)| (t, visible(t, faces, l)))
956                    .min_by(|a, b| b.1.cmp(&a.1).then(nearer(a.0, b.0)))
957            };
958            if accepted(drawn::EDGE) {
959                for e in (l.view.edges.iter()).filter(|e| l.shows_boundary(&e.solid, &e.faces)) {
960                    let mut segments = e.polyline.array_windows().map(|&[a, b]| (a, b));
961                    if let Some((t, seen)) = hit_along(&mut segments, &e.faces) {
962                        let hit = l.hit(&l.view.model, drawn::EDGE, &e.name, ray.at(t), t);
963                        edges.push((hit, seen));
964                    }
965                }
966            }
967            if accepted(drawn::SKETCH_CURVE) {
968                for sketch in l.view.sketches.iter().filter(|s| !l.hides(&s.name)) {
969                    for c in &sketch.curves {
970                        let world = |p: &Vector2| sketch.plane.uv_to_xyz(p);
971                        let mut segments = c
972                            .polyline
973                            .array_windows()
974                            .map(|[a, b]| (world(a), world(b)));
975                        if let Some((t, seen)) = hit_along(&mut segments, &[]) {
976                            let at = ray.at(t);
977                            let hit = l.hit(&sketch.target, drawn::SKETCH_CURVE, &c.id, at, t);
978                            sketch_curves.push((hit, seen));
979                        }
980                    }
981                }
982            }
983        }
984        let seen = |hits: &[(ElementHit, bool)]| {
985            nearest(
986                (hits.iter())
987                    .filter(|(_, seen)| *seen)
988                    .map(|(hit, _)| hit.clone()),
989            )
990        };
991        if first.is_none() {
992            first = seen(&points);
993        }
994        // A sketch curve a feature was built from lies on the edge it made:
995        // which of the two is nearer along the ray is rounding, so an edge
996        // within a reach of the sketch curve hit is taken — the part's own.
997        if first.is_none() {
998            first = match (seen(&edges), seen(&sketch_curves)) {
999                (Some(edge), Some(drawn))
1000                    if edge
1001                        .t
1002                        .definitely_greater(drawn.t.add(pointer.reach_at(1.0, drawn.t))) =>
1003                {
1004                    Some(drawn)
1005                }
1006                (edge, drawn) => edge.or(drawn),
1007            };
1008        }
1009        all.extend((points.into_iter().chain(edges).chain(sketch_curves)).map(|(hit, _)| hit));
1010
1011        let mut areas: Vec<ElementHit> = Vec::new();
1012        if accepted(drawn::FACE) {
1013            for (t, l, f) in &faces {
1014                let point = l.pointer.ray.at(*t);
1015                areas.push(l.hit(&l.view.model, drawn::FACE, &f.name, point, *t));
1016            }
1017        }
1018        for l in &layers {
1019            if accepted(drawn::SKETCH) {
1020                areas.extend(l.view.sketches_under(l));
1021            }
1022            if accepted(drawn::DATUM) {
1023                let extent = Extent {
1024                    center: l.local(self.extent.center),
1025                    size: self.extent.size,
1026                };
1027                areas.extend(l.view.datums_under(l, extent));
1028            }
1029        }
1030        if first.is_none() {
1031            first = nearest(areas.iter().cloned());
1032        }
1033        all.extend(areas);
1034        all.sort_by(|a, b| nearer(a.t, b.t));
1035        let mut under: Vec<ElementHit> = Vec::new();
1036        for hit in first.into_iter().chain(all) {
1037            if !under.iter().any(|u| u.element == hit.element) {
1038                under.push(hit);
1039            }
1040        }
1041        under
1042    }
1043
1044    /// What a click with `pointer` picks of a kind in `accepts`: of what
1045    /// lies [`PartView::under`] it, the one its [`Pointer::cycle`] names.
1046    pub fn pick(
1047        &self,
1048        pointer: &Pointer,
1049        accepts: &[String],
1050        hidden: &[String],
1051    ) -> Option<ElementHit> {
1052        cycled(self.under(pointer, accepts, hidden), pointer.cycle)
1053    }
1054
1055    /// A frame put on each of what the pointer is over, in the order it is
1056    /// under it (see [`FramePick`], [`PartView::frame_on`]), each once.
1057    fn frames_under(&self, pointer: &Pointer, hidden: &[String]) -> Vec<ElementHit> {
1058        let kinds = [
1059            drawn::DATUM,
1060            drawn::VERTEX,
1061            drawn::EDGE,
1062            drawn::FACE,
1063            drawn::SKETCH_POINT,
1064            drawn::SKETCH_CURVE,
1065        ];
1066        let accepts: Vec<String> = kinds.iter().map(|k| k.to_string()).collect();
1067        let layers = self.layers(pointer, hidden);
1068        let mut frames: Vec<ElementHit> = Vec::new();
1069        for hit in self.under(pointer, &accepts, hidden) {
1070            if let Some(frame) = self.frame_on(&layers, hit)
1071                && !frames.iter().any(|f| f.element == frame.element)
1072            {
1073                frames.push(frame);
1074            }
1075        }
1076        frames
1077    }
1078
1079    /// A frame put on `hit`, of what the pointer is over: a face gives its
1080    /// own, at the corner or the side the pointer is near — and in the
1081    /// middle of the face if it is near neither; a vertex of the face under
1082    /// the pointer, the face's at that corner; an edge, its own, at the end
1083    /// the pointer is near; a point or a datum, its own.
1084    fn frame_on(&self, layers: &[Layer<'_>], hit: ElementHit) -> Option<ElementHit> {
1085        let instance = Some(hit.element.target.path()).filter(|path| !path.is_empty());
1086        let layer = layers.iter().find(|l| l.instance == instance)?;
1087        let view = layer.view;
1088        let element = |kind: &str, name: &str| PickedElement {
1089            target: hit.element.target.clone(),
1090            kind: kind.to_string(),
1091            name: name.to_string(),
1092        };
1093        let at = match hit.element.kind.as_str() {
1094            drawn::VERTEX => {
1095                let vertex = view.vertices.iter().find(|v| v.name == hit.element.name)?;
1096                let under = layer.pick_face();
1097                if let Some((_, face)) = under.filter(|(_, f)| vertex.faces.contains(&f.name)) {
1098                    let on = element(drawn::FACE, &face.name);
1099                    let frame = FramePick {
1100                        on,
1101                        at: Some(hit.element.clone()),
1102                    };
1103                    return Some(ElementHit {
1104                        element: frame.picked(),
1105                        ..hit
1106                    });
1107                }
1108                None
1109            }
1110            drawn::EDGE => {
1111                let edge = view.edges.iter().find(|e| e.name == hit.element.name)?;
1112                let (first, last) = (edge.polyline.first()?, edge.polyline.last()?);
1113                let local = layer.local(hit.point);
1114                let reach = last.sub(first).norm().mul(Scalar::from_f64(END_OF_AN_EDGE));
1115                if local.sub(first).norm().definitely_less(reach) {
1116                    Some(element(drawn::VERTEX, &edge.ends[0]))
1117                } else if local.sub(last).norm().definitely_less(reach) {
1118                    Some(element(drawn::VERTEX, &edge.ends[1]))
1119                } else {
1120                    None
1121                }
1122            }
1123            drawn::FACE => (view.corner_or_side_near(&layer.pointer, &hit.element.name))
1124                .map(|(kind, name)| element(kind, &name)),
1125            _ => None,
1126        };
1127        let frame = FramePick {
1128            on: hit.element.clone(),
1129            at,
1130        };
1131        Some(ElementHit {
1132            element: frame.picked(),
1133            ..hit
1134        })
1135    }
1136
1137    /// The corner of the face `face` the pointer is near, or else the side —
1138    /// the vertex or the edge, by its kind and name — within [`NEAR_CORNER`]
1139    /// and [`NEAR_SIDE`] reaches of it, whichever is nearer its ray.
1140    fn corner_or_side_near(&self, pointer: &Pointer, face: &str) -> Option<(&'static str, String)> {
1141        let ray = &pointer.ray;
1142        let corner = (self.vertices.iter())
1143            .filter(|v| v.faces.iter().any(|f| f == face))
1144            .map(|v| (v, ray.distance_to_point(&v.at)))
1145            .filter(|(_, (dist, t))| pointer.within(*dist, *t, NEAR_CORNER))
1146            .min_by(|a, b| nearer(a.1.0, b.1.0))
1147            .map(|(v, _)| (drawn::VERTEX, v.name.clone()));
1148        corner.or_else(|| {
1149            (self.edges.iter())
1150                .filter(|e| e.faces.iter().any(|f| f == face))
1151                .filter_map(|e| {
1152                    (e.polyline.array_windows())
1153                        .map(|[a, b]| ray.distance_to_segment(a, b))
1154                        .filter(|(dist, t)| pointer.within(*dist, *t, NEAR_SIDE))
1155                        .min_by(|a, b| nearer(a.0, b.0))
1156                        .map(|(dist, _)| (e, dist))
1157                })
1158                .min_by(|a, b| nearer(a.1, b.1))
1159                .map(|(e, _)| (drawn::EDGE, e.name.clone()))
1160        })
1161    }
1162
1163    /// Every face of those `shown` the ray enters, with how far along it
1164    /// first does, the nearest first — of two as near, the first in the
1165    /// order of the faces — of the triangles its tree finds the ray could
1166    /// meet (see [`tree`]).
1167    fn faces_entered(
1168        &self,
1169        pointer: &Pointer,
1170        shown: impl Fn(&ViewFace) -> bool,
1171    ) -> Vec<(Scalar, &ViewFace)> {
1172        let mut hits = Vec::new();
1173        self.faces_tree().near(&pointer.ray, |f, t| {
1174            if let Some(face) = self.faces.get(f).filter(|face| shown(face))
1175                && let Some([a, b, c]) = face.mesh.triangles.get(t)
1176                && let Some(hit) = pointer.ray.intersect_triangle(a, b, c)
1177            {
1178                hits.push(((f, t), hit, face));
1179            }
1180        });
1181        hits.sort_by_key(|(at, ..)| *at);
1182        let mut entered: Vec<(usize, Scalar, &ViewFace)> = Vec::new();
1183        for ((f, _), hit, face) in hits {
1184            match entered.last_mut() {
1185                Some((g, t, _)) if *g == f => {
1186                    if nearer(hit, *t).is_lt() {
1187                        *t = hit;
1188                    }
1189                }
1190                _ => entered.push((f, hit, face)),
1191            }
1192        }
1193        entered.sort_by(|a, b| nearer(a.1, b.1));
1194        entered.into_iter().map(|(_, t, face)| (t, face)).collect()
1195    }
1196
1197    /// The nearest face of those `shown` the ray enters (see
1198    /// [`PartView::faces_entered`]).
1199    fn pick_face(
1200        &self,
1201        pointer: &Pointer,
1202        shown: impl Fn(&ViewFace) -> bool,
1203    ) -> Option<(Scalar, &ViewFace)> {
1204        self.faces_entered(pointer, shown).into_iter().next()
1205    }
1206
1207    /// The tree of its faces' triangles: built once, and again only once
1208    /// its faces are others.
1209    fn faces_tree(&self) -> Rc<FaceTree> {
1210        let mut kept = self.faces_tree.borrow_mut();
1211        if let Some(tree) = kept.as_ref().filter(|tree| tree.is_of(&self.faces)) {
1212            return tree.clone();
1213        }
1214        let tree = Rc::new(FaceTree::of(&self.faces));
1215        *kept = Some(tree.clone());
1216        tree
1217    }
1218
1219    /// Every sketch of `layer` hit inside one of its closed regions — the
1220    /// area a viewer shades — or near one of its curves.
1221    fn sketches_under(&self, layer: &Layer<'_>) -> Vec<ElementHit> {
1222        let pointer = &layer.pointer;
1223        let shown = self.sketches.iter().filter(|s| !layer.hides(&s.name));
1224        let hits = shown.filter_map(|sketch| {
1225            let (t, p) = pointer.ray.intersect_uv_plane(&sketch.plane)?;
1226            let reach = pointer.reach_at(1.0, t);
1227            let in_region = sketch
1228                .regions
1229                .iter()
1230                .any(|loops| polygons_contain(loops, &p));
1231            let on_curve = || {
1232                sketch.curves.iter().any(|c| {
1233                    c.polyline
1234                        .array_windows()
1235                        .any(|[a, b]| !p.distance_to_segment(a, b).definitely_greater(reach))
1236                })
1237            };
1238            (in_region || on_curve())
1239                .then(|| layer.hit(&sketch.target, drawn::SKETCH, "", pointer.ray.at(t), t))
1240        });
1241        hits.collect()
1242    }
1243
1244    /// Every datum of `layer` other than a frame the ray hits, as the viewer
1245    /// draws it: a point at its origin, an axis as a line and a plane
1246    /// as a square, each [`Extent::size`] of `extent` — the whole drawing's —
1247    /// long around the point of it nearest the extent's center.
1248    fn datums_under(&self, layer: &Layer<'_>, extent: Extent) -> Vec<ElementHit> {
1249        let pointer = &layer.pointer;
1250        let Extent { center, size } = extent;
1251        let ray = &pointer.ray;
1252        let Ok(half) = size.div(Scalar::TWO) else {
1253            return Vec::new();
1254        };
1255        let shown = self.datums.iter().filter(|d| !layer.hides(&d.name));
1256        let hits = shown.filter_map(|d| {
1257            let f = &d.frame;
1258            let (origin, w) = (f.origin(), f.w());
1259            let t = match d.kind {
1260                DatumKind::Frame => None?,
1261                DatumKind::Point => {
1262                    let (dist, t) = ray.distance_to_point(origin);
1263                    pointer.within(dist, t, 1.0).then_some(t)?
1264                }
1265                DatumKind::Axis => {
1266                    let mid = origin.add(&w.prod_scalar(center.sub(origin).prod_dot(w)));
1267                    let reach = w.prod_scalar(size);
1268                    let (dist, t) = ray.distance_to_segment(&mid.sub(&reach), &mid.add(&reach));
1269                    pointer.within(dist, t, 1.0).then_some(t)?
1270                }
1271                DatumKind::Plane => {
1272                    let (t, point) = ray.intersect_plane(origin, w)?;
1273                    let d = point.sub(&center);
1274                    let inside = |axis: &Vector3| !d.prod_dot(axis).abs().definitely_greater(half);
1275                    (inside(f.u()) && inside(f.v())).then_some(t)?
1276                }
1277            };
1278            Some(layer.hit(&self.datum_target, drawn::DATUM, &d.name, ray.at(t), t))
1279        });
1280        hits.collect()
1281    }
1282
1283    /// The part of a frame datum of `layer` the ray hits, the frame
1284    /// [`FRAME`] reaches tall: its origin ball — the frame as a whole —
1285    /// else an axis (from a tenth of its length to its tip), else a plane's
1286    /// square (off the origin, between the other two axes): every ball,
1287    /// every axis and every square under the pointer — the smallest part
1288    /// under it is the one meant, as for the part's elements.
1289    fn frame_parts_under(&self, layer: &Layer<'_>) -> [Vec<ElementHit>; 3] {
1290        let pointer = &layer.pointer;
1291        let ray = &pointer.ray;
1292        let frac = |size: Scalar, x: f64| size.mul(Scalar::from_f64(x));
1293        let hit = |name: &str, point: Vector3, t: Scalar| {
1294            layer.hit(&self.datum_target, drawn::DATUM, name, point, t)
1295        };
1296        let (mut balls, mut axes, mut planes) = (Vec::new(), Vec::new(), Vec::new());
1297        let frames =
1298            (self.datums.iter()).filter(|d| d.kind == DatumKind::Frame && !layer.hides(&d.name));
1299        for d in frames {
1300            let f = &d.frame;
1301            let origin = f.origin();
1302            let size = pointer.reach_at(FRAME, ray.closest_to_point(origin));
1303            let (dist, t) = ray.distance_to_point(origin);
1304            if !dist.definitely_greater(frac(size, 0.12)) {
1305                balls.push(hit(&d.name, *origin, t));
1306            }
1307            for (component, name) in &d.components {
1308                match *component {
1309                    DatumComponent::Axis(axis) => {
1310                        let dir = axis.of(f);
1311                        let (a, b) = (
1312                            origin.add(&dir.prod_scalar(frac(size, 0.1))),
1313                            origin.add(&dir.prod_scalar(size)),
1314                        );
1315                        let (dist, t) = ray.distance_to_segment(&a, &b);
1316                        if pointer.within(dist, t, 0.6) {
1317                            axes.push(hit(name, b, t));
1318                        }
1319                    }
1320                    DatumComponent::Plane(normal) => {
1321                        let Some((t, point)) = ray.intersect_plane(origin, &normal.of(f)) else {
1322                            continue;
1323                        };
1324                        let local = point.sub(origin);
1325                        let in_square = (FrameAxis::ALL.iter())
1326                            .filter(|&&other| other != normal)
1327                            .all(|other| {
1328                                let x = (local.prod_dot(&other.of(f)).div(size))
1329                                    .unwrap_or(Scalar::INFINITY);
1330                                !x.sub(Scalar::from_f64(0.45))
1331                                    .abs()
1332                                    .definitely_greater(Scalar::from_f64(0.15))
1333                            });
1334                        if in_square {
1335                            planes.push(hit(name, point, t));
1336                        }
1337                    }
1338                }
1339            }
1340        }
1341        [balls, axes, planes]
1342    }
1343}
1344
1345impl Default for PartView {
1346    fn default() -> Self {
1347        Self::new()
1348    }
1349}
1350
1351thread_local! {
1352    static PARTS_DRAWN: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
1353    static FACES_DRAWN: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
1354}
1355
1356/// How many faces this thread has drawn ([`FaceMesh::new`]) ever: what
1357/// showing a part drawn before, with other sketches, must not do — so a
1358/// test bounds it by counting these, not by timing it.
1359pub fn faces_drawn() -> usize {
1360    FACES_DRAWN.get()
1361}
1362
1363/// How many parts this thread has drawn ([`PartView::finish`]) ever.
1364/// Drawing a part is what a pointer event must not do, so a test can bound
1365/// the work an event does by counting these, rather than timing it.
1366pub fn parts_drawn() -> usize {
1367    PARTS_DRAWN.get()
1368}
1369
1370/// A part as drawn, but what the viewer was told not to draw: what is
1371/// seen, which a step editor picks in (see [`Scene`]) — the part before
1372/// the step, or what the step built, as the viewer shows it.
1373#[derive(Clone, Copy, Debug)]
1374pub struct Visible<'v> {
1375    pub view: &'v PartView,
1376    /// What is not drawn, sorted: [`crate::editor::SceneState::hidden`].
1377    pub hidden: &'v [String],
1378}
1379
1380/// A part as drawn, all of it shown.
1381impl Scene for PartView {
1382    fn under(&self, pointer: &Pointer, accepts: &[String]) -> Vec<ElementHit> {
1383        PartView::under(self, pointer, accepts, &[])
1384    }
1385
1386    fn hit_instance(&self, name: &str, pointer: &Pointer) -> Option<Scalar> {
1387        self.pick_instance(name, pointer, &[])
1388    }
1389}
1390
1391impl<'v> Visible<'v> {
1392    /// The placed part a drag at `pointer` moves (see
1393    /// [`PartView::part_to_drag`]), of those drawn.
1394    pub fn part_to_drag(&self, pointer: &Pointer) -> Option<(&'v ViewInstance, Scalar)> {
1395        self.view.part_to_drag(pointer, self.hidden)
1396    }
1397}
1398
1399impl Scene for Visible<'_> {
1400    fn under(&self, pointer: &Pointer, accepts: &[String]) -> Vec<ElementHit> {
1401        self.view.under(pointer, accepts, self.hidden)
1402    }
1403
1404    fn hit_instance(&self, name: &str, pointer: &Pointer) -> Option<Scalar> {
1405        self.view.pick_instance(name, pointer, self.hidden)
1406    }
1407}
1408
1409/// The nearest of `hits` along the ray.
1410fn nearest(hits: impl IntoIterator<Item = ElementHit>) -> Option<ElementHit> {
1411    hits.into_iter().min_by(|a, b| nearer(a.t, b.t))
1412}