Terms
Description
TriangleMesh.diffraction_edges_mask returns jnp.ones(...), marking every edge as a diffraction edge. The docstring says this is a placeholder. Without fixing this you can't identify which edges to diffract on, can't get wedge angles for UTD, and can't build path candidate graphs that include diffraction.
I'd add edge adjacency computation (ideally in Rust) and fix the placeholder:
@property
def edge_adjacency(self) -> tuple[Int[Array, "num_triangles 3"], Int[Array, "num_triangles 3"]]:
"""Adjacent triangle index and shared edge index per triangle edge.
-1 for boundary edges. Edge i connects vertex[i] to vertex[(i+1) % 3].
"""
@property
def diffraction_edges_mask(self) -> Bool[Array, "num_triangles 3"]:
"""True for non-planar wedge edges: two adjacent triangles whose
dihedral angle is not ~pi (not coplanar)."""
@property
def wedge_angles(self) -> Float[Array, "num_triangles 3"]:
"""Exterior wedge angle n*pi per edge. n=2 for flat, n=1.5 for 90-degree corner."""
@property
def diffraction_edge_vertices(self) -> Float[Array, "num_diffraction_edges 2 3"]:
"""Start and end vertices of each diffraction edge."""
The core operation is building an edge-to-face adjacency map: hash sorted vertex-index pairs per triangle, find pairs. Rust is the right place for this (differt-core/src/geometry/triangle_mesh.rs) since it's topology on large meshes (Munich has ~40K triangles), it's not JIT-traceable, and the Rust mesh infrastructure is already there. Cache the result as NumPy on the Python side.
For non-manifold edges (>2 adjacent triangles) I'd just mark them as non-diffraction and log a warning.
One nice property: when assume_quads is set, the shared diagonal of two triangles forming a quad is coplanar. The dihedral angle check handles that naturally.
For testing: a box scene should detect 12 exterior wedge edges at corners and 0 on coplanar diagonals. A flat plane should detect 0. Munich as a sanity check for building corners and rooftop edges.
This is a prerequisite for #429 (diffraction_coefficients), which needs wedge_angles (the n parameter for UTD). #431 (transition_matrices) also needs it for its diffraction branch. And fermat_path_on_linear_objects in differt.rt already knows how to trace paths on edges, it just doesn't know which edges to use yet.
Terms
Description
TriangleMesh.diffraction_edges_maskreturnsjnp.ones(...), marking every edge as a diffraction edge. The docstring says this is a placeholder. Without fixing this you can't identify which edges to diffract on, can't get wedge angles for UTD, and can't build path candidate graphs that include diffraction.I'd add edge adjacency computation (ideally in Rust) and fix the placeholder:
The core operation is building an edge-to-face adjacency map: hash sorted vertex-index pairs per triangle, find pairs. Rust is the right place for this (
differt-core/src/geometry/triangle_mesh.rs) since it's topology on large meshes (Munich has ~40K triangles), it's not JIT-traceable, and the Rust mesh infrastructure is already there. Cache the result as NumPy on the Python side.For non-manifold edges (>2 adjacent triangles) I'd just mark them as non-diffraction and log a warning.
One nice property: when
assume_quadsis set, the shared diagonal of two triangles forming a quad is coplanar. The dihedral angle check handles that naturally.For testing: a box scene should detect 12 exterior wedge edges at corners and 0 on coplanar diagonals. A flat plane should detect 0. Munich as a sanity check for building corners and rooftop edges.
This is a prerequisite for #429 (
diffraction_coefficients), which needswedge_angles(thenparameter for UTD). #431 (transition_matrices) also needs it for its diffraction branch. Andfermat_path_on_linear_objectsindiffert.rtalready knows how to trace paths on edges, it just doesn't know which edges to use yet.