Coverage for src/beamme/mesh_creation_functions/nurbs_utils.py: 100%
29 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-28 15:20 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-28 15:20 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2018-2026 BeamMe Authors
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22"""This file has utility functions for handling NURBS."""
24import numpy as _np
26from beamme.core.conf import bme as _bme
27from beamme.core.rotation import Rotation as _Rotation
30def ensure_3d_splinepy_object(splinepy_obj) -> None:
31 """Ensure that a given splinepy object has 3D control points.
33 Args:
34 splinepy_obj:
35 Splinepy object to ensure 3D, if this is an object with fewer than
36 3 dimensions, it will be converted to 3D by adding the missing
37 coordinates with a value of 0.
38 """
39 control_points_dim = splinepy_obj.control_points.shape[1]
40 if control_points_dim == 3:
41 pass
42 elif control_points_dim < 3:
43 # Add "empty" coordinates to make control points 3D
44 control_points_3d = _np.zeros([len(splinepy_obj.control_points), 3])
45 control_points_3d[:, :control_points_dim] = splinepy_obj.control_points
46 splinepy_obj.control_points = control_points_3d
47 else:
48 raise ValueError(
49 f"Splinepy object must be 1D, 2D or 3D, but has {control_points_dim} dimensions."
50 )
53def translate_splinepy(splinepy_obj, vector) -> None:
54 """Translate a splinepy object by a vector.
56 Args:
57 vector: _np.array, list
58 2D/3D vector to translate the splinepy object.
59 """
60 if not len(vector) == splinepy_obj.control_points.shape[1]:
61 raise ValueError(
62 f"Dimensions of translation vector and splinepy object do not match: {len(vector)} != {splinepy_obj.control_points.shape[1]}"
63 )
65 for point in splinepy_obj.control_points:
66 point += vector
69def rotate_splinepy(splinepy_obj, rotation: _Rotation, origin=None) -> None:
70 """Rotate a splinepy object by a rotation object."""
71 rotation_matrix = rotation.get_rotation_matrix()
73 dimension = splinepy_obj.control_points.shape[1]
74 if dimension == 2:
75 if not _np.allclose(
76 rotation_matrix[2, :], [0, 0, 1], rtol=0, atol=_bme.eps_quaternion
77 ) or not _np.allclose(
78 rotation_matrix[:, 2], [0, 0, 1], rtol=0, atol=_bme.eps_quaternion
79 ):
80 raise ValueError(
81 "Rotation vector must be in the x-y plane for 2D splinepy objects."
82 )
83 rotation_matrix = rotation_matrix[:2, :2]
85 if origin is None:
86 origin = _np.zeros(dimension)
88 for i_point, point in enumerate(splinepy_obj.control_points):
89 point_new = _np.dot(rotation_matrix, point - origin) + origin
90 splinepy_obj.control_points[i_point] = point_new