differt.rt.triangles_visible_from_vertices#
- triangles_visible_from_vertices(vertices, 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_latticeto 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_frustumto only launch rays in a spatial region that contains triangles.- Parameters:
vertices (
Float[ArrayLike, '*#batch 3']) –An array of vertices, used as origins of the rays.
Usually, this would be an array of transmitter positions.
triangle_vertices (
Float[ArrayLike, '*#batch num_triangles 3 3']) – An array of triangle vertices.active_triangles (
Bool[ArrayLike, '*#batch num_triangles']|None) –An optional array of boolean values indicating which triangles are active, i.e., should be considered for intersection.
If not specified, all triangles are considered active.
num_rays (
int) –The number of rays to launch.
The larger, the more accurate.
The number of rays to process in a single batch. This allows to make a trade-off between memory usage and performance.
The batch size is automatically adjusted to be the minimum of the number of rays and the specified batch size.
If
None, the batch size is set to the number of rays.kwargs (
Any) – Keyword arguments passed torays_intersect_triangles.
- Return type:
- Returns:
For each triangle, whether it intersects with any of the rays.
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_vertices, ... ) >>> 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_vertices( ... 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_vertices( ... 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