forked from 1b-agent/fieldcraft-upstream
engine, ui: mesh.node.relax and relaxation fields, Relax Nodes tool with sphere and preview (#398)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
75f9e5ae6e
commit
94fdbf0fca
19 files changed
+1038
-9
No files matched your search
+2
-1
@@ -6,7 +6,7 @@ Every entry is a toolbar button. **Ready** entries run their command; **coming s
|
||||
shown greyed with the roadmap milestone that brings them (ROADMAP.md). Scripts, the command line,
|
||||
the control channel and AI agents over MCP (docs/mcp.md) run the same commands.
|
||||
|
||||
70 ready, 39 coming soon.
|
||||
71 ready, 39 coming soon.
|
||||
|
||||
## Geometry
|
||||
|
||||
@@ -50,6 +50,7 @@ the control channel and AI agents over MCP (docs/mcp.md) run the same commands.
|
||||
| Edit | Element — Add an element on existing nodes | ready | `mesh.element.add`, `mesh.element.remove`, `mesh.clear` |
|
||||
| Edit | Mirror Mesh — Mirror a body's mesh across a plane, joined on the plane (mesh half a symmetric part) | ready | `mesh.mirror` |
|
||||
| Edit | Merge Nodes — Merge coincident nodes, keeping sets, loads and boundary conditions on the survivors; check for duplicates and cracks, renumber | ready | `mesh.node.merge`, `mesh.check.duplicates`, `mesh.renumber` |
|
||||
| Improve | Relax Nodes — Relax the nodes inside a sphere to fix spikes and slivers; surface nodes slide on the geometry; kept as a field to apply again after a remesh | ready | `mesh.node.relax`, `mesh.node.relax.apply` |
|
||||
| Edit | Remesh Region — Remesh a region in place; split and collapse elements | coming soon (M6) | |
|
||||
| Edit | Orphan Mesh — Import a mesh without geometry | coming soon (M6) | |
|
||||
| Verify | Quality — Quality metrics and the certified validity check, failing elements listed | ready | `mesh.quality` |
|
||||
|
||||
+18
@@ -167,6 +167,24 @@ edges of partition cells matching counts.
|
||||
4. `mesh.seed.list` lists the seeds and the edges they reach (`stale` when the design has no such
|
||||
edge); `mesh.seed.clear {edges?}` removes them. Seeds are saved with the model.
|
||||
|
||||
## Relaxing a few bad elements
|
||||
|
||||
When `mesh.quality` shows a handful of spikes in an otherwise good mesh:
|
||||
|
||||
1. `execute` `mesh.node.relax {"around_element": <the scaled Jacobian's worst>}` (or `{"center":
|
||||
[x, y, z], "radius": r}`, or `nodes` / `elements` / `set`; `iterations`, `strength`, `falloff`).
|
||||
Nodes there relax (smart Laplacian, then optimization of the worst element), each move kept
|
||||
only when the worst element around the node does not get worse and nothing inverts. Nodes on a
|
||||
B-rep face slide in its UV parameters and stay on it, nodes on a B-rep edge slide along it,
|
||||
vertex nodes stay; nodes on a partition cut face move freely (both cells share them). The
|
||||
reply gives the nodes moved, the largest displacement, and the region's smallest scaled
|
||||
Jacobian, largest edge ratio and worst elements before and after. One undo step.
|
||||
2. The relaxation is kept as a field of the model (`field`, default `Relax1`, …; saved with it).
|
||||
After a remesh, `mesh.node.relax.apply {"field": "Relax1"}` puts the relaxed shape on the new
|
||||
mesh (each node takes the displacement interpolated in the old cell it lies in, on its face,
|
||||
then one guarded smoothing sweep); with `"reapply": true` on the relaxation every remesh does
|
||||
it by itself (the mesher's reply lists `relaxations_applied`).
|
||||
|
||||
## Limits
|
||||
|
||||
The server treats its input as hostile. A message line may be at most 16 MiB (the control
|
||||
|
||||
@@ -952,6 +952,25 @@ input points), Steiner points kept half the local spacing from the boundary.
|
||||
is exact: a planar bilinear quad's Jacobian is affine in each reference coordinate, so four exact `orient2d` corner
|
||||
tests decide it.
|
||||
|
||||
### B7a. Node relaxation of a finished mesh (implemented in `fieldcraft-mesh::relax`, `mesh.node.relax`)
|
||||
|
||||
- **Method.** Smart Laplacian (S. Canann, J. Tristano, M. Staten, *An approach to combined Laplacian and
|
||||
optimization-based smoothing for triangular, quadrilateral, and quad-dominant meshes*, IMR 1998; L. Freitag 1997
|
||||
above): a node's weighted step toward the centroid of its edge neighbours is kept only when the worst element
|
||||
around it does not get worse and no element inverts, halved otherwise. Then one step up the gradient of the worst
|
||||
element's quality (the active max–min element of Freitag and Ollivier-Gooch, IJNME 40, 1997; P. Knupp, IJNME 48,
|
||||
2000), kept only when it raises the worst. Quality is the scaled Jacobian of `crate::quality`; validity its
|
||||
certified check.
|
||||
- **Surface nodes in UV.** A node on a B-rep face moves in the face's own parameters (the displacement resolved on
|
||||
the surface's coordinate directions, then the surface evaluated there), so it stays exactly on an analytic face;
|
||||
free-form faces fall back to projection onto the face's tessellation (SolidCraft's kernel exposes the analytic
|
||||
surfaces only). Nodes on a B-rep edge slide along it; vertex nodes are held; partition cut faces are not
|
||||
geometry, so their nodes move freely.
|
||||
- **Relaxation fields.** What a relaxation did is kept as the relaxed region's cells before and after; a later
|
||||
mesh takes the displacement at each node's parametric coordinates in the old cell holding it (barycentric or
|
||||
trilinear shape functions), slides it onto its face or edge, undoes any move that would invert an element, and
|
||||
smooths once (`mesh.node.relax.apply`, or `reapply` after every remesh).
|
||||
|
||||
---
|
||||
|
||||
### B8. Mapped and swept hexahedral meshing (implemented in `fieldcraft-mesh::hex`)
|
||||
|
||||
Reference in new issue
Block a user