Source code for scimba_torch.geometry.utils

"""Some utility functions."""

import numpy as np
import torch


[docs] def compute_bounding_box(points: torch.Tensor, inflation: float = 0.05) -> torch.Tensor: """Compute a bounding box for a vector of points. Args: points: the vector of points, shape (batch, d). inflation: the factor for inflation. Returns: A bounding box of shape (d,2) containing all the points. Raises: ValueError: points is not a vector of n points of dim d """ if not (points.ndim == 2): raise ValueError(f"first argument must be a tensor (n, d), got {points.shape}") if points.shape[1] == 0: return torch.tensor([]) bounding_box = torch.stack( ( torch.min(points, dim=0, keepdim=False)[0], torch.max(points, dim=0, keepdim=False)[0], ), dim=-1, ) # print("bounding_box: ", bounding_box) # inflate the bounding box maxwidth = torch.max(bounding_box[:, 1] - bounding_box[:, 0]) inflated_bb = ( torch.ones_like( bounding_box, dtype=torch.get_default_dtype(), device=torch.get_default_device(), ) * (inflation / 2.0) * maxwidth ) inflated_bb[:, 0] = bounding_box[:, 0] - inflated_bb[:, 0] inflated_bb[:, 1] = bounding_box[:, 1] + inflated_bb[:, 1] return inflated_bb
[docs] def write_points_normals_to_file( points: np.ndarray | torch.Tensor, normals: np.ndarray | torch.Tensor, filename: str, delimiter: str = " ", ) -> None: """Writes the couple of points, normals to a text file. Args: points: the tensor of points; shape must be [n,d]. normals: the tensor of normals; shape must be [n,d]. filename: the file to write to. delimiter: the delimiter, default is whitespace. Raises: ValueError: input tensors does not have appropriated shape. """ if not ( (points.ndim == 2) and (normals.ndim == 2) and (points.shape[0] == normals.shape[0]) and (points.shape[1] == normals.shape[1]) ): raise ValueError( "first and second arguments mustbe tensors of the same shape (n,d)" ) with open(filename, "w") as f: for i in range(points.shape[0]): # Convertir chaque élément en chaîne avec une précision maximale linep = delimiter.join(f"{x:.18e}" for x in points[i].tolist()) linen = delimiter.join(f"{x:.18e}" for x in normals[i].tolist()) f.write(linep + delimiter + linen + "\n")
[docs] def read_points_normals_from_file( filename: str, delimiter: str = " ", ) -> tuple[torch.Tensor, torch.Tensor]: """Reads points and normals from file. Args: filename: file to read from. delimiter: the delimiter, default is whitespace. Returns: a tuple of points, normals Raises: ValueError: input file does not have an even number of columns. """ points_normals = np.loadtxt( filename, dtype=np.float64, ndmin=2, delimiter=delimiter ) dim = points_normals.shape[1] if dim % 2: raise ValueError("there must be an even number of columns in input file") dim = dim // 2 points, normals = points_normals[:, :dim], points_normals[:, dim:] return ( torch.tensor( points, dtype=torch.get_default_dtype(), device=torch.get_default_device() ), torch.tensor( normals, dtype=torch.get_default_dtype(), device=torch.get_default_device() ), )