forked from 1b-agent/fieldcraft-upstream
render: symbols for boundary conditions, loads and interactions, and scene labels
glyphs::Glyphs picks where a model's setup symbols go (resolving its sets once, thinning them on a grid, capping each definition and sampling large ones with a note) and draws them into a Scene at the nodes' current positions: cones for constrained translations (and rotations where nodes rotate), arrows for forces, double-headed arrows for moments, arrows normal to pressure faces, one arrow for gravity and body forces, a curved arrow for centrifugal loads, crosses with names for reference points, lines for couplings, hatched squares for rigid walls. Colours come from the caller by role, muted over results. Scene gains labels, drawn by the CPU rasterizer with a small bitmap font of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
95c02bc728
commit
93f1a03137
6 files changed
+1137
-5
No files matched your search
@@ -103,7 +103,7 @@ fn face_key(e: &[u32], face: &[usize]) -> Option<[u32; 4]> {
|
||||
}
|
||||
|
||||
/// Newell's normal of a polygon (robust for non-planar quads); `None` when degenerate.
|
||||
fn polygon_normal(p: &[Vec3]) -> Option<Vec3> {
|
||||
pub(crate) fn polygon_normal(p: &[Vec3]) -> Option<Vec3> {
|
||||
let mut n = Vec3::ZERO;
|
||||
for (i, a) in p.iter().enumerate() {
|
||||
let b = p.get((i + 1) % p.len()).copied().unwrap_or(*a);
|
||||
@@ -112,7 +112,7 @@ fn polygon_normal(p: &[Vec3]) -> Option<Vec3> {
|
||||
n.normalized()
|
||||
}
|
||||
|
||||
fn centre(p: &[Vec3]) -> Vec3 {
|
||||
pub(crate) fn centre(p: &[Vec3]) -> Vec3 {
|
||||
p.iter().fold(Vec3::ZERO, |s, q| s + *q) * (1.0 / p.len().max(1) as f64)
|
||||
}
|
||||
|
||||
@@ -243,6 +243,11 @@ impl DisplayMesh {
|
||||
}
|
||||
}
|
||||
|
||||
/// Where node `label` is drawn, if it is (nodes are kept in label order).
|
||||
pub fn node_position(&self, label: u32) -> Option<Vec3> {
|
||||
self.nodes.binary_search_by_key(&label, |n| n.label).ok().and_then(|i| self.nodes.get(i)).map(|n| n.p)
|
||||
}
|
||||
|
||||
/// The node nearest to where a ray (`origin`, `dir`) first hits an element face ahead of
|
||||
/// its origin: the hit face's closest corner, and the hit point. Line elements and geometry
|
||||
/// are not hit.
|
||||
|
||||
Reference in new issue
Block a user