differt.rt.triangles_visible_from_vertex

differt.rt.triangles_visible_from_vertex#

triangles_visible_from_vertex(vertex, triangle_vertices, active_triangles=None, num_rays=1000000, batch_size=512, **kwargs)[source]#

Return whether triangles are visible from vertex positions.

This function uses ray launching and fibonacci_lattice to estimate whether a given triangle can be reached from a specific vertex, i.e., with a ray path, without interacting with any other triangle facet.

It also uses viewing_frustum to only launch rays in a spatial region that contains triangles.

Note

This function has a faster and more memory-efficient equivalent method: TriangleMesh.triangles_visible_from_vertex, as long as smoothing is not required.

Parameters:
Return type:

Bool[Array, '*batch num_triangles']

Returns:

Boolean mask, True if each triangle is visible from the corresponding vertex.

Examples

The following example shows how to identify triangles as visible from a given transmitter, coloring them in dark gray.

>>> import equinox as eqx
>>> from differt.rt import (
...     triangles_visible_from_vertex,
... )
>>> from differt.scene import (
...     TriangleScene,
...     get_sionna_scene,
...     download_sionna_scenes,
... )
>>>
>>> download_sionna_scenes()
>>> file = get_sionna_scene("simple_street_canyon")
>>> scene = TriangleScene.load_xml(file)
>>> scene = eqx.tree_at(
...     lambda s: s.transmitters, scene, jnp.array([-33, 0, 32.0])
... )
>>> visible_triangles = triangles_visible_from_vertex(
...     scene.transmitters,
...     scene.mesh.triangle_vertices,
... )
>>> visible_color = jnp.array([0.2, 0.2, 0.2])
>>> scene = eqx.tree_at(
...     lambda s: s.mesh.face_colors,
...     scene,
...     scene.mesh.face_colors.at[visible_triangles, :].set(visible_color),
... )
>>> fig = scene.plot(backend="plotly")
>>> fig

In this example, a receiver is placed at the opposite side of the street canyon, and its visible triangles are colored in blue. Triangles that are visible from both the transmitter and the receiver are colored in yellow.

>>> scene = eqx.tree_at(
...     lambda s: s.receivers, scene, jnp.array([33, 0, 1.5])
... )
>>> visible_triangles = triangles_visible_from_vertex(
...     jnp.stack((scene.transmitters, scene.receivers)),
...     scene.mesh.triangle_vertices,
... )
>>> triangles_visible_from_tx = visible_triangles[0, :]
>>> triangles_visible_from_rx = visible_triangles[1, :]
>>> visible_by_tx_color = jnp.array([0.2, 0.2, 0.2])
>>> visible_by_rx_color = jnp.array([0.2, 0.8, 0.2])
>>> visible_by_both_color = jnp.array([0.8, 0.8, 0.2])
>>> scene = eqx.tree_at(
...     lambda s: s.mesh.face_colors,
...     scene,
...     scene.mesh.face_colors.at[triangles_visible_from_tx, :].set(
...         visible_by_tx_color
...     ),
... )
>>> scene = eqx.tree_at(
...     lambda s: s.mesh.face_colors,
...     scene,
...     scene.mesh.face_colors.at[triangles_visible_from_rx, :].set(
...         visible_by_rx_color
...     ),
... )
>>> scene = eqx.tree_at(
...     lambda s: s.mesh.face_colors,
...     scene,
...     scene.mesh.face_colors.at[
...         triangles_visible_from_tx & triangles_visible_from_rx, :
...     ].set(visible_by_both_color),
... )
>>> fig = scene.plot(backend="plotly")
>>> fig