geoclide.trianglemesh module#

Triangle and triangle mesh shapes.

This module implements the triangle-based shapes of geoclide, along with functions creating meshes approximating a sphere or a disk, and readers of meshes from gcnc netcdf files or from any format supported by the trimesh package (stl, obj, ply, …).

Key Classes#

Triangle

A single triangle described by its three vertices p0, p1 and p2, with the ray intersection tests of pbrt v2 and v3.

TriangleMesh

A set of triangles described by an array of vertices and an array of faces, with intersection tests vectorized over the rays and the triangles. A mesh can be converted to an xarray dataset and written to a gcnc netcdf file.

class geoclide.trianglemesh.Triangle(p0: Point | None = None, p1: Point | None = None, p2: Point | None = None, otw: Transform | None = None, wto: Transform | None = None, p0t: Point | None = None, p1t: Point | None = None, p2t: Point | None = None)[source]#

Bases: Shape

Creation of the class Triangle

Parameters:
p0Point

The first point(s) of the triangle(s)

p1Point

The second point(s) of the triangle(s)

p2Point

The the third point(s) of the triangle(s)

otwTransform, optional

From object to world space or the transformation applied to the triangle

wtoTransform, optional

From world to object space or the in inverse transformation applied to the triangle

p0tPoint, optional

If given circumvent the automatically computed p0t (p0 after applying transformation)

p1tPoint, optional

If given circumvent the automatically computed p1t (p1 after applying transformation)

p2tPoint, optional

If given circumvent the automatically computed p2t (p2 after applying transformation)

Methods

area()

compute the area of the triangle

intersect(...)

Test if a ray/set of rays intersect with the triangle(s) and return intersection information

intersect_v2(...)

intersect_v3(...)

is_intersection(r[, method, diag_calc])

Test if a ray/set of rays intersect with the triangle(s)

is_intersection_t(r[, method, diag_calc])

Test if a ray/set of rays intersect with the triangle(s)

is_intersection_v2(r[, diag_calc])

is_intersection_v2_t(r[, diag_calc])

is_intersection_v3(r, diag_calc)

is_intersection_v3_t(r[, diag_calc])

area() float | ndarray[source]#

compute the area of the triangle

Warning

the scale transformation is not considered for the area calculation!

intersect(r: Ray, method: str = 'v3', diag_calc: bool = False, *, ds_output: Literal[True] = True) Dataset[source]#
intersect(r: Ray, method: str = 'v3', diag_calc: bool = False, *, ds_output: Literal[False]) tuple
intersect(r: Ray, method: str = 'v3', diag_calc: bool = False, *, ds_output: bool) Dataset | tuple

Test if a ray/set of rays intersect with the triangle(s) and return intersection information

Parameters:
rRay

The ray(s) to use for the intersection test(s)

methodstr, optional

Two choices -> ‘v2’ (use mainly pbrt v2 intersection test method) or ‘v3’ (pbrt v3)

diag_calcbool, optional

Perform diagonal calculations in case Triangle and Ray have ndarray point components, meaning the output is a 1-D array instead of a 2-D array where out[i] is calculated using r(i) and triangle(i). The same size for the Triangle and the Ray is required.

ds_outputbool, optional

If True the output is a dataset, else return a tuple with intersection information variables

Returns:
Dataset or tuple

Xarray dataset containing the intersection information if ds_output is True (see the get_intersect_dataset function of the shapes module for its variables), else a tuple ready to be an input for that same function. Form of the tuple:

  • shape_namestr

    -> The shape class name

  • rRay

    -> The ray(s) used for the intersection test

  • tNone or float or ndarray

    -> The t ray variable(s) for its first intersection at the shape surface. An ndarray is 1-D, or 2-D for a set of rays and a set of triangles.

  • is_intersectionbool or ndarray

    -> If there is an intersection return True, else False. An ndarray is an ndarray of booleans, 1-D, or 2-D for a set of rays and a set of triangles.

  • uNone or float or ndarray

    -> The u coordinate(s) of the parametric representation. An ndarray is 1-D, or 2-D for a set of rays and a set of triangles.

  • vNone or float or ndarray

    -> The v coordinate(s) of the parametric representation. An ndarray is 1-D, or 2-D for a set of rays and a set of triangles.

  • dpduNone or ndarray

    -> The surface partial derivative(s) of phit with respect to u. An ndarray is 1-D, or 2-D in case of a set of rays and/or a set of triangles.

  • dpdvNone or ndarray

    -> The surface partial derivative(s) of phit with respect to v. An ndarray is 1-D, or 2-D in case of a set of rays and/or a set of triangles.

  • diag_calcbool

    -> This indicates whether a diagonal calculation has been performed

Notes

By default the ‘v3’ method is used since there are more robustness tests. But the ‘v2’ method is at least twice faster than ‘v3’.

is_intersection(r: Ray, method: str = 'v3', diag_calc: bool = False) bool | ndarray[source]#

Test if a ray/set of rays intersect with the triangle(s)

Parameters:
rRay

The ray(s) to use for the intersection test(s)

methodstr, optional

Two choices -> ‘v2’ (use mainly pbrt v2 intersection test method) or ‘v3’ (pbrt v3)

diag_calcbool, optional

Perform diagonal calculations in case Triangle and Ray have ndarray point components, meaning the output is a 1-D array instead of a 2-D array where out[i] is calculated using r(i) and triangle(i). The same size for the Triangle and the Ray is required.

Returns:
bool or ndarray

If there is an intersection -> True, else False. In case of an ndarray, it is an ndarray of booleans, 1-D, or 2-D for a set of rays and a set of triangles

is_intersection_t(r: Ray, method: str = 'v3', diag_calc: bool = False) tuple[float | ndarray | None, bool | ndarray][source]#

Test if a ray/set of rays intersect with the triangle(s)

Parameters:
rRay

The ray(s) to use for the intersection test(s)

methodstr, optional

Two choices -> ‘v2’ (use mainly pbrt v2 intersection test method) or ‘v3’ (pbrt v3)

diag_calcbool, optional

Perform diagonal calculations in case Triangle and Ray have ndarray point components, meaning the output is a 1-D array instead of a 2-D array where out[i] is calculated using r(i) and triangle(i). The same size for the Triangle and the Ray is required.

Returns:
thitNone or float or ndarray

The t ray variable(s) for its first intersection at the shape surface. In case of an ndarray, it is 1-D, or 2-D for a set of rays and a set of triangles

is_intersectionbool or ndarray

If there is an intersection -> True, else False. In case of an ndarray, it is an ndarray of booleans, 1-D, or 2-D for a set of rays and a set of triangles

class geoclide.trianglemesh.TriangleMesh(vertices: ndarray, faces: ndarray, otw: Transform | None = None, wto: Transform | None = None)[source]#

Bases: Shape

Creation of the class TriangleMesh

Parameters:
verticesndarray

The vertices xyz coordinates. It is a 2d ndarray of size (nvertices, 3) where the first element is the coordinate of first vertex and so on

facesndarray

The vertices indices of triangles, a 2d ndarray of shape (ntriangles, 3). The 3 first indices are the vertices (p0, p1 and p3) indices of the first triangle and so on

otwTransform, optional

From object to world space or the transformation applied to the triangle mesh

wtoTransform, optional

From world to object space or the in inverse transformation applied to the triangle mesh

Methods

apply_tf(t)

Apply transformation to the triangle mesh

area()

compute the area of the triangle mesh

intersect(...)

Test if a ray/set of rays intersect with the triangle mesh and return intersection information

is_intersection(r[, method, diag_calc, use_loop])

Test if a ray/set of rays intersect with the triangle mesh

is_intersection_t(r[, method, diag_calc, ...])

Test if a ray/set of rays intersect with the triangle mesh

plot([source, savefig_name])

Plot the triangle mesh

to_dataset([name])

Create an xarray dataset where the triangle mesh information are stored

write(path, **kwargs)

Save the mesh

apply_tf(t: Transform) None[source]#

Apply transformation to the triangle mesh

Parameters:
tTranform

The transfomation matrix to apply

area() float[source]#

compute the area of the triangle mesh

Warning

the scale transformation is not considered for the area calculation!

intersect(r: Ray, method: str = 'v3', diag_calc: bool = False, *, ds_output: Literal[True] = True, use_loop: bool = False) Dataset[source]#
intersect(r: Ray, method: str = 'v3', diag_calc: bool = False, *, ds_output: Literal[False], use_loop: bool = False) tuple
intersect(r: Ray, method: str = 'v3', diag_calc: bool = False, *, ds_output: bool, use_loop: bool = False) Dataset | tuple

Test if a ray/set of rays intersect with the triangle mesh and return intersection information

Parameters:
rRay

The ray(s) to use for the intersection test(s)

methodstr, optional

Two choices -> ‘v2’ (use mainly pbrt v2 triangle intersection test method) or ‘v3’ (pbrt v3)

diag_calcbool, optional

Perform diagonal calculations between r(i) and triangle(i). The number of triangles must be equal to the number of rays

use_loopbool, optional

If True -> scalar calculations over a loop (instead of using numpy). It can be useful for debugging

ds_outputbool, optional

If True the output is a dataset, else return a tuple with intersection information variables

Returns:
Dataset or tuple

Xarray dataset containing the intersection information if ds_output is True (see the get_intersect_dataset function of the shapes module for its variables), else a tuple ready to be an input for that same function. Form of the tuple:

  • shape_namestr

    -> The shape class name

  • rRay

    -> The ray(s) used for the intersection test

  • tNone or float or ndarray

    -> The t ray variable(s) for its first intersection at the shape surface. An ndarray is 1-D.

  • is_intersectionbool or ndarray

    -> If there is an intersection return True, else False. An ndarray is a 1-D ndarray of booleans.

  • uNone or float or ndarray

    -> The u coordinate(s) of the parametric representation. An ndarray is 1-D.

  • vNone or float or ndarray

    -> The v coordinate(s) of the parametric representation. An ndarray is 1-D.

  • dpduNone or ndarray

    -> The surface partial derivative(s) of phit with respect to u. An ndarray is 1-D, or 2-D for a set of rays.

  • dpdvNone or ndarray

    -> The surface partial derivative(s) of phit with respect to v. An ndarray is 1-D, or 2-D for a set of rays.

  • diag_calcbool

    -> This indicates whether a diagonal calculation has been performed

is_intersection(r: Ray, method: str = 'v3', diag_calc: bool = False, use_loop: bool = False) bool | ndarray[source]#

Test if a ray/set of rays intersect with the triangle mesh

Parameters:
rRay

The ray(s) to use for the intersection test(s)

methodstr, optional

Two choices -> ‘v2’ (use mainly pbrt v2 triangle intersection test method) or ‘v3’ (pbrt v3)

diag_calcbool, optional

Perform diagonal calculations between r(i) and triangle(i). The number of triangles must be equal to the number of rays

use_loopbool, optional

If True -> scalar calculations over a loop (instead of using numpy). It can be useful for debugging

Returns:
bool or ndarray

If there is an intersection -> True, else False. In case of an ndarray, it is a 1-D ndarray of booleans

is_intersection_t(r: Ray, method: str = 'v3', diag_calc: bool = False, use_loop: bool = False) tuple[float | ndarray | None, bool | ndarray][source]#

Test if a ray/set of rays intersect with the triangle mesh

Parameters:
rRay

The ray(s) to use for the intersection test(s)

methodstr, optional

Two choices -> ‘v2’ (use mainly pbrt v2 triangle intersection test method) or ‘v3’ (pbrt v3)

diag_calcbool, optional

Perform diagonal calculations between r(i) and triangle(i). The number of triangles must be equal to the number of rays

use_loopbool, optional

If True -> scalar calculations over a loop (instead of using numpy). It can be useful for debugging

Returns:
thitNone or float or ndarray

The t ray variable(s) for its first intersection at the shape surface. In case of an ndarray, it is 1-D

is_intersectionbool or ndarray

If there is an intersection -> True, else False. In case of an ndarray, it is a 1-D ndarray of booleans

Notes

If use_loop = True, is_intersection_t can be significantly more consuming than is_intersection. Because it does not stop at the first intersection, but it finalize the complete loop to return the thit corresponding to the nearest triangle.

plot(source: str | None = None, savefig_name: str | None = None, **kwargs)[source]#

Plot the triangle mesh

Parameters:
sourcestr

The package used for the plot, only 2 option -> ‘matplotlib’ or ‘trimesh’. If source = None, use matplolib for mesh with ntriangle < 5000, else use trimesh

savefig_namestr, optional

If savefig_name is given, the figure is saved with the given name (only if source=’matplotlib)

**kwargs

All other keyword arguments are passed on to matplotlib plot_trisurf function. For example: alpha, color, shade, … If source = ‘trimesh’ then the keyword arguments passed on to show Trimesh method

Examples

>>> import geoclide as gc
>>> prolate = gc.Spheroid(radius_xy=1.5, radius_z=3.)
>>> msh = prolate.to_trianglemesh()
>>> msh.plot(color='green', edgecolor='k')
to_dataset(name: str = 'none') Dataset[source]#

Create an xarray dataset where the triangle mesh information are stored

Parameters:
namestr, optional

The name of the triangle mesh to be stored

Returns:
Dataset

Xarray dataset containing the triangle mesh information.

Key variables included:

  • obj_names: The name(s) of the mesh(es)

  • vertices: The vertices xyz coordinates [nobj, nvertices, xyz]

  • faces: For each triangle, the indices of its vertices p0, p1 and p2 [nobj, ntriangles, p0p1p2]

write(path: str, **kwargs) None[source]#

Save the mesh

  • if gcnc format use xarray, else use trimesh

Parameters:
pathstr

The xarray to_netcdf path paramter (or trimesh)

**kwargs

The keyword arguments are passed on to xarray to_netcdf or trimesh export method

geoclide.trianglemesh.read_gcnc_trianglemesh(path: str, **kwargs) TriangleMesh[source]#

Read geoclide netcdf4 format and convert it to a TriangleMesh class object

Parameters:
pathstr

The xarray filename_or_obj parameter

**kwargs

The keyword arguments are passed on to xarray open_dataset method

Returns:
TriangleMesh

The triangle mesh

geoclide.trianglemesh.read_trianglemesh(path: str, **kwargs) TriangleMesh[source]#

Open mesh file

  • if gcnc format use xarray, else use trimesh

Parameters:
pathstr

The xarray filename_or_obj or trimesh file_obj parameter

**kwargs

The keyword arguments are passed on to xarray open_dataset or trimesh load_mesh method

Returns:
TriangleMesh

The triangle mesh

Notes

A file describing several objects, as a glb file or an obj file with several groups, is read as a single triangle mesh gathering all of them.