Skip to content

Commit f080ee6

Browse files
authored
FILT: Add the HierarchicalSmooth triangle mesh smoothing algorithm (#1551)
* FILT: Add the HierarchicalSmooth triangle mesh smoothing algorithm * ENH: Code quality improvements for HierarchicalSmooth filter - Add const-correctness to function parameters throughout the algorithm - Remove redundant EdgePairEqual struct (std::pair already has operator==) - Change fastChainLinkSort windingDict to std::map for cross-platform determinism - Remove unused Triangulation members (m_Mesh, m_SubTri, m_EdgeList) and accessors - Use dense Eigen matrices for vertex data instead of sparse (2.7x perf improvement) - Add throttled messaging and cancel checks in processing loop - Use std::move for Eigen matrix transfer to avoid copies - Switch boundary dict to OrderedEdgeDict (std::map) for reproducible results - Update test to use exemplar-based comparison with correct error threshold --------- Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net>
1 parent 021a4f7 commit f080ee6

11 files changed

+1409
-0
lines changed

src/Plugins/SimplnxCore/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ set(FilterList
8787
FeatureFaceCurvatureFilter
8888
FillBadDataFilter
8989
FlyingEdges3DFilter
90+
HierarchicalSmoothFilter
9091
IdentifyDuplicateVerticesFilter
9192
IdentifySampleFilter
9293
InitializeDataFilter
@@ -248,6 +249,7 @@ set(AlgorithmList
248249
FillBadData
249250
FindNRingNeighbors
250251
FlyingEdges3D
252+
HierarchicalSmooth
251253
IdentifyDuplicateVertices
252254
IdentifySample
253255
InitializeData
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Hierarchical Smoothing
2+
3+
## Group (Subgroup)
4+
5+
Surface Meshing (Smoothing)
6+
7+
## Description
8+
9+
This **Filter** applies hierarchical smoothing to a triangle surface mesh representing polycrystalline grain boundary networks. Unlike simple Laplacian smoothing, this algorithm respects the topological hierarchy of the mesh:
10+
11+
1. **Quad points** (node type 4 or 14) are held fixed as they represent the intersection of four or more grains.
12+
2. **Triple lines** (edges between quad points along triple junctions) are smoothed as 1D curves with the quad points as fixed endpoints.
13+
3. **Interior boundary surfaces** are smoothed with the already-smoothed triple lines held fixed, solving a Dirichlet boundary value problem using a conjugate gradient solver.
14+
15+
This hierarchical approach preserves the topology of the grain boundary network while producing smooth surfaces. The smoothing parameter is optimized via interval bisection to balance smoothness against displacement from the original mesh.
16+
17+
Nodes that are displaced beyond the error threshold (a multiple of a reference edge length) are rejected and reset to their original positions.
18+
19+
## Algorithm Overview
20+
21+
22+
## Algorithm Overview
23+
24+
The filter applies smoothing in three hierarchical stages. Each stage's output is held fixed during subsequent stages, preserving the topology of the grain boundary network.
25+
26+
![Algorithm Overview — 3 Hierarchical Stages](Images/HierarchicalSmooth_algorithm_overview.png)
27+
28+
The three stages are:
29+
30+
1. **Fix Quad Points** — Vertices where four or more grains meet (node types 4/14) are identified and permanently locked. These topological invariants anchor the entire boundary network.
31+
2. **Smooth Triple Lines** — The 1D curves along triple junctions (node types 3/13) are smoothed as independent curves between fixed quad-point endpoints, using bisection-optimized conjugate gradient.
32+
3. **Smooth Interior Surfaces** — The 2D boundary surfaces (node types 2/12) are smoothed with the triple lines held fixed, solving a constrained Dirichlet boundary value problem via conjugate gradient.
33+
34+
## Parameter Details
35+
36+
### Max Bisection Iterations
37+
38+
At each stage, the algorithm must find the optimal **smoothing parameter** `epsilon` that balances two competing goals: (1) keeping vertices close to their original positions, and (2) minimizing surface curvature. This is framed as solving a weighted linear system:
39+
40+
```
41+
((1 - epsilon) * I + epsilon * L^T * L) * y = (1 - epsilon) * y_original - epsilon * L^T * k
42+
\_____________/ \_______________/ \________________________/ \______________/
43+
identity term smoothness term data fidelity term boundary term
44+
```
45+
46+
where `I` is the identity matrix, `L` is the reduced graph Laplacian, `y_original` is the original vertex positions, and `k` encodes the fixed boundary constraints.
47+
48+
- When `epsilon = 0`: vertices stay at their original positions (no smoothing).
49+
- When `epsilon = 1`: vertices are fully smoothed to minimize curvature (maximum smoothing).
50+
51+
The algorithm uses **interval bisection** to find the optimal `epsilon`:
52+
53+
54+
1. Start at `epsilon = 0.5`.
55+
2. Compute a numerical derivative of the objective function (the total Laplacian residual energy).
56+
3. If the derivative is near zero (flat region), the current `epsilon` is not in the active tradeoff zone. Halve `epsilon` and try again.
57+
4. Repeat until either a significant slope is found or the iteration limit is reached.
58+
59+
The **Max Bisection Iterations** parameter controls how many halvings are attempted. The default value of **53** comes from `log2(10^16) ~ 53`, which is the number of bisection steps needed to resolve a double-precision floating point value to machine epsilon. In practice, the search often converges in far fewer iterations because it terminates early once a significant slope is detected.
60+
61+
**Practical guidance:**
62+
63+
| Value | Effect |
64+
|-------|--------|
65+
| 10-20 | Faster execution per boundary. May find a slightly sub-optimal smoothing parameter, but the difference is usually negligible for well-behaved meshes. |
66+
| 53 (default) | Machine-precision search. Guarantees the best possible smoothing parameter for each boundary. |
67+
| >53 | No additional benefit beyond the default since double-precision arithmetic cannot distinguish values at this resolution. |
68+
69+
70+
![](Images/HierarchicalSmooth_max_bisection_iterations.png)
71+
72+
### Error Threshold
73+
74+
After all boundaries have been smoothed, the algorithm performs a post-processing validation step. Each vertex's displacement from its original position is compared against a **reference length** derived from the mesh:
75+
76+
```
77+
Reference length = sqrt(3) * min(edge0_length, edge1_length)
78+
```
79+
80+
where the edge lengths come from the first triangle in the mesh. This approximates the characteristic size scale of one mesh element (the height of an equilateral triangle with side length equal to the shortest edge).
81+
82+
Each vertex's displacement is normalized by this reference length:
83+
84+
```
85+
normalized_displacement = || vertex_smoothed - vertex_original || / reference_length
86+
```
87+
88+
Any vertex whose normalized displacement exceeds the **Error Threshold** is **rejected**: its position is reset to the original (unsmoothed) value, and it is marked as "not smoothed."
89+
90+
This safety mechanism prevents the smoothing from producing mesh artifacts in regions where the solver produces an extreme solution (e.g., highly elongated triangles, unusual boundary conditions, or degenerate configurations).
91+
92+
**Practical guidance:**
93+
94+
| Value | Effect |
95+
|-------|--------|
96+
| 0.5 - 1.0 | Very conservative. Vertices cannot move more than 0.5-1.0 reference lengths. Produces results closer to the original mesh but may leave some regions under-smoothed. Good for preserving fine detail. |
97+
| 2.0 (default) | Moderate. Allows vertices to move up to 2x the reference length. Good general-purpose setting that provides effective smoothing while catching genuine outliers. |
98+
| 5.0 - 10.0 | Permissive. Allows large displacements. Produces smoother results but risks mesh quality degradation if a boundary solver produces a pathological solution. |
99+
| Very large (>100) | Effectively disables rejection. All smoothed positions are accepted regardless of displacement. Only use if you are confident the input mesh is well-conditioned. |
100+
101+
![](Images/HierarchicalSmooth_error_threshold.png)
102+
103+
## Parameters
104+
105+
| Name | Type | Description | Default |
106+
|------|------|-------------|---------|
107+
| Max Bisection Iterations | Int32 | Maximum number of bisection iterations for smoothing parameter optimization (see above) | 53 |
108+
| Error Threshold | Float64 | Displacement rejection threshold as a multiple of the reference edge length (see above) | 2.0 |
109+
| Triangle Geometry | Geometry Selection | The triangle geometry to smooth | - |
110+
| Node Type | Array Selection (Int8, 1-comp) | Array specifying node type (2=interior, 3=triple, 4=quad; +10 for surface) | - |
111+
| Face Labels | Array Selection (Int32, 2-comp) | Array specifying grain IDs on either side of each face | - |
112+
113+
## Notes
114+
115+
- This filter modifies the vertex coordinates of the input Triangle Geometry **in place**.
116+
- The algorithm processes each grain boundary independently. Progress messages indicate which boundary is being processed.
117+
- Volume surface nodes (types 12, 13, 14) are treated identically to their interior counterparts (types 2, 3, 4) for the purpose of the smoothing hierarchy.
118+
- The conjugate gradient solver handles its own internal convergence; the max iterations parameter controls only the bisection search for the optimal smoothing parameter, not the CG solver iterations.
119+
- If the filter reports rejected nodes, consider increasing the Error Threshold or inspecting the input mesh for degenerate triangles near the rejected vertices.
120+
121+
% Auto generated parameter table will be inserted here
122+
123+
## Reference
124+
125+
- S. Maddali, "HierarchicalSmooth" - Topology-aware smoothing for polycrystalline grain boundary networks. Carnegie Mellon University, 2016-2018.
126+
- S. Maddali, S. Ta'asan, R. M. Suter, Topology-faithful nonparametric estimation and tracking of bulk interface networks, Computational Materials Science 125, 328-340 (2016).
127+
128+
## Example Pipelines
129+
130+
## License & Copyright
131+
132+
Please see the description file distributed with this plugin.
133+
134+
## DREAM3D Mailing Lists
135+
136+
If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions.
371 KB
Loading
140 KB
Loading
109 KB
Loading

0 commit comments

Comments
 (0)