diff --git a/bladex/blade.py b/bladex/blade.py index 161c666..74f52f5 100644 --- a/bladex/blade.py +++ b/bladex/blade.py @@ -463,6 +463,83 @@ def rotate(self, deg_angle=None, rad_angle=None, axis='x'): elif id == 3: self.root_face = face + def mirror(self, *args, **kwargs): + """ + 3D mirroring of the blade with respect to a plane. + The plane can be defined either by three points or by a point and its normal direction. + Which option to be used depends on the inputs taken by the funtion. + + args: -three entries means three points + -two entries means one point and one normal vector + kwargs: -only accepted arguments: point1, point2, point3, normal + """ + if len(self.blade_coordinates_up) == 0: + raise ValueError('You must apply transformations before rotation.') + + if len(args) + len(kwargs) not in [2, 3]: + raise ValueError("Wrong number of arguments") + + admissible_kwargs = ['point1', 'point2', 'point3', 'point', 'normal'] + if any(key not in admissible_kwargs for key in kwargs.keys()): + raise ValueError('Wrong argument. Admissible arguments are only {}'.format(admissible_kwargs)) + + from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform + from OCC.Core.gp import gp_Pnt + from OCC.Core.gp import gp_Vec + from OCC.Core.gp import gp_Dir + from OCC.Core.gp import gp_Ax2 + from OCC.Core.gp import gp_Trsf + + if len(args) == 3: + # Case where the three points are passed + point1 = gp_Pnt(*args[0]) + point2 = gp_Pnt(*args[1]) + point3 = gp_Pnt(*args[2]) + # Two vectors defining the directions of the plane + vector1 = gp_Vec(point1, point2) + vector2 = gp_Vec(point2, point3) + # Normal versor to the plane passing through the three points + normal = gp_Dir(vector1.Crossed(vector2)) + elif list(kwargs.keys()) == ['point1', 'point2', 'point3']: + # Case where the three points are passed + point1 = gp_Pnt(*kwargs['point1']) + point2 = gp_Pnt(*kwargs['point2']) + point3 = gp_Pnt(*kwargs['point3']) + # Two vectors defining the directions of the plane + vector1 = gp_Vec(point1, point2) + vector2 = gp_Vec(point2, point3) + # Normal versor to the plane passing through the three points + normal = gp_Dir(vector1.Crossed(vector2)) + elif len(args) == 2: + # Case where one point and the normal are passed + point1 = gp_Pnt(*args[0]) + normal = gp_Dir(*args[1]) + elif sorted(kwargs.keys()) == sorted(['point', 'normal']): + point1 = gp_Pnt(*kwargs['point']) + normal = gp_Dir(*kwargs['normal']) + else: + raise ValueError('Wrong arguments passed') + + # Ax2 object identifying the plane + ax2 = gp_Ax2(point1, normal) + + # Mirroring wrt plane transformation + trsf = gp_Trsf() + trsf.SetMirror(ax2) + + for id, face in enumerate([self.upper_face, self.lower_face, + self.tip_face, self.root_face]): + brep_tr = BRepBuilderAPI_Transform(face, trsf, True, True) + face = brep_tr.Shape() + if id == 0: + self.upper_face = face + elif id == 1: + self.lower_face = face + elif id == 2: + self.tip_face = face + elif id == 3: + self.root_face = face + def scale(self, factor): """ Scale the blade coordinates by a specified factor. diff --git a/bladex/deform.py b/bladex/deform.py index 8c26d46..1fdda05 100644 --- a/bladex/deform.py +++ b/bladex/deform.py @@ -305,7 +305,7 @@ def compute_deformed_parameters(self, param, tol=1e-3): if index.shape[0] > 1: # In case more neighbors are found, then take first value only. index = index[0] - self.deformed_parameters[param][i] = self.spline[param][index, 1] + self.deformed_parameters[param][i] = self.spline[param][index, 1].item() def compute_all(self, rbf_points=1000, diff --git a/tests/test_blade.py b/tests/test_blade.py index c09f75c..91da27c 100644 --- a/tests/test_blade.py +++ b/tests/test_blade.py @@ -386,6 +386,18 @@ def test_rotate_rad(self): np.testing.assert_almost_equal(blade.blade_coordinates_down[1][2], rotated_coordinates) + def test_blade_mirror_exceptions(self): + blade = create_sample_blade_NACA() + blade.apply_transformations() + with self.assertRaises(ValueError): + blade.mirror(wrong_argument=[0., 0., 0.], point2=[0., 1., 0.], point3=[0., 1., 1.]) + + def test_blade_mirror_exceptions_2(self): + blade = create_sample_blade_NACA() + blade.apply_transformations() + with self.assertRaises(ValueError): + blade.mirror([0., 1., 1.]) + def test_plot_view_elev_init(self): blade = create_sample_blade_NACA() blade.apply_transformations()