mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-09 12:32:52 +00:00
Walk the PRC product tree into placed, coloured tessellations. - PrcFile::placements / placements_with(StyleAlpha, EntityOverrides): every drawable tessellation reached from the model file's roots, placed by its occurrence path's locations and then the representation item's local coordinate systems (a 4x4 Matrix) [WD 7.3.10.1, 7.6.3.2]. - Colours: styles and materials from the file structure globals, the father/son inheritance bits [WD 7.2.4.2], style transparency combined with material alpha by StyleAlpha, per-face styles and topology references via Placement::triangle_colours. A prototype's part is coloured by its own structure's styles. A colour index counts the colour array's doubles (pdf-issues #816). - Occurrences' entity references: colour, hide or relocate the entity they name, in the occurrence's subtree, everywhere, or not at all. - PrcFile::model_tree: the assembly tree as a model-tree panel lists it, with name sources, visibility and each node's placement range. - TriangleMesh::transformed applies a Matrix: positions, cofactor-mapped normals, winding flipped under a mirror. Never panics: occurrence and prototype cycles are Malformed; depth 64, 2^20 visits, MAX_PLACEMENTS and a face-override ceiling bound the walk; counts are checked against the remaining data before allocating. Markups, views, scene lights and clipping planes are Unsupported; textures are read past. Field orders the working draft leaves open follow prc-rs (MIT); each is marked `// prc-rs:`, as are the step-1 container, Double and schema choices that did. Adapted from pdfcer (MIT, same author), crates/pdfcer-3d/src/tree and vec3.rs at 0c9742b5936232af89cd707138ef149dc1f4a660. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
69 lines
2.7 KiB
Rust
69 lines
2.7 KiB
Rust
//! The assembly tree as a list: what a model-tree panel shows.
|
|
|
|
use std::ops::Range;
|
|
|
|
/// Where a [`ModelNode`]'s name came from. PRC does not say which name a
|
|
/// viewer should show; this reader takes the first present of these, in order.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
#[non_exhaustive]
|
|
pub enum NameSource {
|
|
/// The occurrence's own name.
|
|
Occurrence,
|
|
/// The name of an occurrence in its prototype chain.
|
|
Prototype,
|
|
/// The name of the part definition it draws.
|
|
Part,
|
|
/// No name anywhere: [`ModelNode::name`] is `None`.
|
|
Unnamed,
|
|
}
|
|
|
|
/// One product occurrence of a PRC model's assembly tree, as
|
|
/// [`PrcFile::model_tree`](crate::PrcFile::model_tree) lists it: depth
|
|
/// first, a parent before its children, children in file order.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
#[non_exhaustive]
|
|
pub struct ModelNode {
|
|
/// The name to show, by [`Self::name_from`]; `None` when unnamed.
|
|
pub name: Option<String>,
|
|
/// Where [`Self::name`] came from.
|
|
pub name_from: NameSource,
|
|
/// Index of the parent node in the list; `None` for a root.
|
|
pub parent: Option<usize>,
|
|
/// 0 for a root.
|
|
pub depth: usize,
|
|
/// Index into [`crate::PrcFile::file_structures`] of the structure
|
|
/// holding this occurrence.
|
|
pub file_structure: usize,
|
|
/// The occurrence's 0-based index in that structure's tree.
|
|
pub occurrence: usize,
|
|
/// The occurrence's own graphics hide it (Show clear, or Removed)
|
|
/// [WD 7.2.4.2]: the visibility the file stores, which a viewer opens on.
|
|
pub hidden: bool,
|
|
/// The occurrence is suppressed (`product_behavior`) [WD 7.3.10].
|
|
pub suppressed: bool,
|
|
/// Whether anything of this node is drawn: false when it or an
|
|
/// ancestor is hidden or suppressed.
|
|
pub drawn: bool,
|
|
/// Whether the occurrence (or its prototype) carries a part definition,
|
|
/// i.e. geometry of its own rather than only children.
|
|
pub has_part: bool,
|
|
/// The placements this node and its descendants draw: indices into
|
|
/// [`PrcFile::placements`](crate::PrcFile::placements) (or
|
|
/// [`placements_with`](crate::PrcFile::placements_with), which yields the same order):
|
|
/// the meshes attributed to this occurrence's part and its descendants' parts. Empty when
|
|
/// nothing under it is drawn.
|
|
pub placements: Range<usize>,
|
|
}
|
|
|
|
impl ModelNode {
|
|
/// The label the node is listed under: its name, or `occurrence F:I`
|
|
/// (file structure, occurrence) when it has none.
|
|
#[must_use]
|
|
pub fn label(&self) -> String {
|
|
match &self.name {
|
|
Some(name) => name.clone(),
|
|
None => format!("occurrence {}:{}", self.file_structure, self.occurrence),
|
|
}
|
|
}
|
|
}
|