Coverage for src / beamme / mesh_creation_functions / nurbs_utils.py: 100%
29 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-21 12:57 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-21 12:57 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2018-2025 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 """
40 control_points_dim = splinepy_obj.control_points.shape[1]
41 if control_points_dim == 3:
42 pass
43 elif control_points_dim < 3:
44 # Add "empty" coordinates to make control points 3D
45 control_points_3d = _np.zeros([len(splinepy_obj.control_points), 3])
46 control_points_3d[:, :control_points_dim] = splinepy_obj.control_points
47 splinepy_obj.control_points = control_points_3d
48 else:
49 raise ValueError(
50 f"Splinepy object must be 1D, 2D or 3D, but has {control_points_dim} dimensions."
51 )
54def translate_splinepy(splinepy_obj, vector) -> None:
55 """Translate a splinepy object by a vector.
57 Args:
58 vector: _np.array, list
59 2D/3D vector to translate the splinepy object.
60 """
62 if not len(vector) == splinepy_obj.control_points.shape[1]:
63 raise ValueError(
64 f"Dimensions of translation vector and splinepy object do not match: {len(vector)} != {splinepy_obj.control_points.shape[1]}"
65 )
67 for point in splinepy_obj.control_points:
68 point += vector
71def rotate_splinepy(splinepy_obj, rotation: _Rotation, origin=None) -> None:
72 """Rotate a splinepy object by a rotation object."""
74 rotation_matrix = rotation.get_rotation_matrix()
76 dimension = splinepy_obj.control_points.shape[1]
77 if dimension == 2:
78 if not _np.allclose(
79 rotation_matrix[2, :], [0, 0, 1], rtol=0, atol=_bme.eps_quaternion
80 ) or not _np.allclose(
81 rotation_matrix[:, 2], [0, 0, 1], rtol=0, atol=_bme.eps_quaternion
82 ):
83 raise ValueError(
84 "Rotation vector must be in the x-y plane for 2D splinepy objects."
85 )
86 rotation_matrix = rotation_matrix[:2, :2]
88 if origin is None:
89 origin = _np.zeros(dimension)
91 for i_point, point in enumerate(splinepy_obj.control_points):
92 point_new = _np.dot(rotation_matrix, point - origin) + origin
93 splinepy_obj.control_points[i_point] = point_new