Source code for capytaine.new_meshes.geometry

# Copyright 2025 Mews Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import numpy as np


[docs] def get_vertices_face(face, vertices): if len(face) == 4 and face[2] != face[3]: return ( vertices[face[0]], vertices[face[1]], vertices[face[2]], vertices[face[3]], ) else: return vertices[face[0]], vertices[face[1]], vertices[face[2]]
[docs] def compute_faces_normals(vertices, faces): normals = [] for face in faces: if len(face) == 4 and face[2] != face[3]: normal = _quad_normal(vertices, face[0], face[1], face[2], face[3]) else: normal = _triangle_normal(vertices, face[0], face[1], face[2]) normals.append(normal) return np.array(normals)
[docs] def compute_faces_areas(vertices, faces): areas = [] for face in faces: verts = get_vertices_face(face, vertices) if len(verts) == 4: a, b, c, d = verts area1 = 0.5 * np.linalg.norm(np.cross(b - a, c - a)) area2 = 0.5 * np.linalg.norm(np.cross(c - a, d - a)) areas.append(area1 + area2) else: a, b, c = verts areas.append(0.5 * np.linalg.norm(np.cross(b - a, c - a))) return np.array(areas)
[docs] def compute_faces_centers(vertices, faces): centers = [] for face in faces: verts = get_vertices_face(face, vertices) if len(verts) == 4: a, b, c, d = verts area1 = 0.5 * np.linalg.norm(np.cross(b - a, c - a)) area2 = 0.5 * np.linalg.norm(np.cross(c - a, d - a)) c1 = (a + b + c) / 3 c2 = (a + c + d) / 3 center = (c1 * area1 + c2 * area2) / (area1 + area2) else: a, b, c = verts center = (a + b + c) / 3 centers.append(center) return np.array(centers)
[docs] def compute_faces_radii(vertices, faces): centers = compute_faces_centers(vertices, faces) distances = [] for face, center in zip(faces, centers): d = compute_distance_between_points(vertices[face[0]], center) distances.append(d) return np.array(distances)
def _triangle_normal(vertices, v0_idx, v1_idx, v2_idx): """ Compute normal vector of a triangle face. Parameters ---------- vertices : ndarray Vertex coordinate array. v0_idx, v1_idx, v2_idx : int Indices of triangle vertices. Returns ------- np.ndarray Normalized normal vector (3,) """ v0, v1, v2 = vertices[v0_idx], vertices[v1_idx], vertices[v2_idx] normal = np.cross(v1 - v0, v2 - v0) return normal / np.linalg.norm(normal) def _quad_normal(vertices, v0_idx, v1_idx, v2_idx, v3_idx): """ Compute normal vector of a quadrilateral face via diagonals. Parameters ---------- vertices : ndarray Vertex coordinate array. v0_idx, v1_idx, v2_idx, v3_idx : int Indices of quad vertices. Returns ------- np.ndarray Normalized normal vector (3,) """ v0, v1, v2, v3 = ( vertices[v0_idx], vertices[v1_idx], vertices[v2_idx], vertices[v3_idx], ) ac = v2 - v0 bd = v3 - v1 normal = np.cross(ac, bd) return normal / np.linalg.norm(normal)
[docs] def compute_distance_between_points(a, b): """ Compute Euclidean distance between two points in n-dimensional space. Parameters ---------- a, b : array_like Coordinate arrays (length 3 or more). Returns ------- float Euclidean distance. """ a = np.asarray(a) b = np.asarray(b) return np.linalg.norm(b - a)