From 61491a156f8eb2cf439100c18b55d2b44b6b2e79 Mon Sep 17 00:00:00 2001 From: Giulio Ortali Date: Wed, 12 Feb 2025 15:46:43 +0100 Subject: [PATCH 01/13] update to newest python-occ version --- bladex/reversepropeller.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bladex/reversepropeller.py b/bladex/reversepropeller.py index f735130..83806c6 100644 --- a/bladex/reversepropeller.py +++ b/bladex/reversepropeller.py @@ -19,7 +19,7 @@ BRep_Tool_CurveOnSurface) import OCC.Core.TopoDS from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse -from OCC.Core.BRepAlgo import BRepAlgo_Section +from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Section from OCC.Core.TopTools import TopTools_ListOfShape, TopTools_MapOfShape from OCC.Core.TopExp import TopExp_Explorer from OCC.Core.TopAbs import TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE, TopAbs_WIRE @@ -29,7 +29,7 @@ from OCC.Core.TopoDS import TopoDS_Shape from OCC.Core.TColgp import TColgp_HArray1OfPnt, TColgp_Array1OfPnt from OCC.Core.GeomAPI import GeomAPI_Interpolate, GeomAPI_IntCS, GeomAPI_ProjectPointOnSurf -from OCC.Core.BRepAdaptor import BRepAdaptor_Curve, BRepAdaptor_HCurve +from OCC.Core.BRepAdaptor import BRepAdaptor_Curve from OCC.Core.GCPnts import GCPnts_AbscissaPoint from OCC.Core.BRep import BRep_Tool from OCC.Core.IntTools import IntTools_FClass2d @@ -38,7 +38,7 @@ from OCC.Core.TopoDS import topods, TopoDS_Edge, TopoDS_Compound from subprocess import call from OCC.Core.IntCurvesFace import IntCurvesFace_ShapeIntersector -from OCC.Core.Adaptor3d import Adaptor3d_Curve, Adaptor3d_HCurve +from OCC.Core.Adaptor3d import Adaptor3d_Curve from OCC.Core.Geom import Geom_Line from OCC.Display.SimpleGui import init_display from OCC.Core.BRepGProp import (brepgprop_LinearProperties, @@ -48,8 +48,8 @@ from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder from OCC.Core.GeomLProp import GeomLProp_SLProps from OCC.Core.GCPnts import GCPnts_AbscissaPoint -from OCC.Core.BRepAdaptor import (BRepAdaptor_Curve, BRepAdaptor_HCurve, - BRepAdaptor_CompCurve, BRepAdaptor_HCompCurve) +from OCC.Core.BRepAdaptor import (BRepAdaptor_Curve, + BRepAdaptor_CompCurve) from OCC.Core.GCPnts import GCPnts_UniformDeflection from OCC.Core.GeomAPI import GeomAPI_PointsToBSpline from OCC.Core.GeomAbs import (GeomAbs_C0, GeomAbs_G1, GeomAbs_C1, GeomAbs_G2, From 4a74208a3ae95c709c8ea170536d20c46dba6bc4 Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Tue, 18 Feb 2025 15:01:34 +0100 Subject: [PATCH 02/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index 71025ea..e681324 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -13,14 +13,14 @@ jobs: fail-fast: false matrix: os: [windows-latest, macos-latest, ubuntu-latest] - python-version: [3.7, 3.8] + python-version: [3.8, 3.9] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} From a934bc87916b95723bcdf50e83edae5c77fd64c9 Mon Sep 17 00:00:00 2001 From: Giulio Ortali Date: Fri, 28 Feb 2025 14:34:49 +0100 Subject: [PATCH 03/13] interpolant 5% curve --- bladex/blade.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/bladex/blade.py b/bladex/blade.py index e516cb5..39f1a98 100644 --- a/bladex/blade.py +++ b/bladex/blade.py @@ -429,8 +429,6 @@ def scale(self, factor): self.blade_coordinates_down[i][1] = new_coord_matrix_down[1] self.blade_coordinates_down[i][2] = new_coord_matrix_down[2] - - def plot(self, elev=None, azim=None, ax=None, outfile=None): """ Plot the generated blade sections. @@ -1088,7 +1086,59 @@ def generate_stl_blade(self, filename): write_stl_file(self.sewed_full, filename) - def generate_iges_blade(self, filename): + def _generate_leading_edge_curves(self): + """ + Private method to generate curves that follow the leading edge of the blade + (top and bottom surfaces). + """ + self._import_occ_libs() + + # Extract points at leftmost 5% for upper and lower surfaces + upper_points = [] + lower_points = [] + + for i in range(self.n_sections): + min_x = np.min(self.sections[i].xdown_coordinates) + max_x = np.max(self.sections[i].xdown_coordinates) + delta_x = max_x - min_x + + target_x = min_x + 0.95 * delta_x + + idx = np.abs(self.sections[i].xdown_coordinates - target_x).argmin() + + # Create points for upper and lower curves + upper_points.append(gp_Pnt( + 1000 * self.blade_coordinates_up[i][0][idx], + 1000 * self.blade_coordinates_up[i][1][idx], + 1000 * self.blade_coordinates_up[i][2][idx] + )) + + lower_points.append(gp_Pnt( + 1000 * self.blade_coordinates_down[i][0][idx], + 1000 * self.blade_coordinates_down[i][1][idx], + 1000 * self.blade_coordinates_down[i][2][idx] + )) + + # Create arrays of points for interpolation + upper_array = TColgp_HArray1OfPnt(1, len(upper_points)) + lower_array = TColgp_HArray1OfPnt(1, len(lower_points)) + + for i, (up, low) in enumerate(zip(upper_points, lower_points)): + upper_array.SetValue(i + 1, up) + lower_array.SetValue(i + 1, low) + + # Create interpolated curves + upper_curve = GeomAPI_Interpolate(upper_array, False, 1e-9) + lower_curve = GeomAPI_Interpolate(lower_array, False, 1e-9) + + upper_curve.Perform() + lower_curve.Perform() + + # Convert to edges + self.upper_le_edge = BRepBuilderAPI_MakeEdge(upper_curve.Curve()).Edge() + self.lower_le_edge = BRepBuilderAPI_MakeEdge(lower_curve.Curve()).Edge() + + def generate_iges_blade(self, filename, include_le_curves=False): """ Generate and export the .IGES file for the entire blade. This method requires PythonOCC (7.4.0) to be installed. @@ -1099,11 +1149,20 @@ def generate_iges_blade(self, filename): self._generate_lower_face(max_deg=1) self._generate_root(max_deg=1) self._generate_tip(max_deg=1) + + if include_le_curves: + self._generate_leading_edge_curves() + iges_writer = IGESControl_Writer() iges_writer.AddShape(self.generated_upper_face) iges_writer.AddShape(self.generated_lower_face) iges_writer.AddShape(self.generated_root) iges_writer.AddShape(self.generated_tip) + + if include_le_curves: + iges_writer.AddShape(self.upper_le_edge) + iges_writer.AddShape(self.lower_le_edge) + iges_writer.Write(filename) @staticmethod @@ -1244,6 +1303,7 @@ def export_ppg(self, if i == len(hub_offsets) - 1: output_string += str("%.8e" % offset[0]) + ' ' + str( "%.8e" % hub_offsets[i][1]) + continue output_string += str("%.8e" % offset[0]) + ' ' + str( "%.8e" % offset[1]) + '\n' From 7c489f1b00ca2016abc9279f5b611853bda47ba9 Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Thu, 6 Mar 2025 17:35:06 +0100 Subject: [PATCH 04/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index e681324..5d972e8 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -24,17 +24,16 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Setup conda - uses: s-weigand/setup-conda@v1.1.1 + - name: Setup Conda + uses: conda-incubator/setup-miniconda@v3 with: - update-conda: true + auto-update-conda: true python-version: ${{ matrix.python-version }} - conda-channels: anaconda, conda-forge - + - name: Install Python dependencies on Linux/MacOS if: startsWith(matrix.os, 'windows') != true run: | - conda install --yes pythonocc-core=7.4.1 + conda install --yes pythonocc-core python3 -m pip install --upgrade pip python3 -m pip install smithers[vtk] python3 -m pip install .[test] @@ -42,7 +41,7 @@ jobs: - name: Install Python dependencies on Windows if: startsWith(matrix.os, 'windows') run: | - conda install --yes pythonocc-core=7.4.1 + conda install --yes pythonocc-core python -m pip install --upgrade pip python -m pip install smithers[vtk] python -m pip install .[test] From 505afb64f5f82a8b8f35a4ec90647798712ae13a Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Thu, 6 Mar 2025 17:38:36 +0100 Subject: [PATCH 05/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index 5d972e8..7065236 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -28,6 +28,7 @@ jobs: uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true + channels: conda-forge,defaults python-version: ${{ matrix.python-version }} - name: Install Python dependencies on Linux/MacOS From 7fa2e241f93d7f19a8823793c0b46d563f6eeea0 Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Thu, 6 Mar 2025 17:46:31 +0100 Subject: [PATCH 06/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index 7065236..a45056d 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -35,9 +35,9 @@ jobs: if: startsWith(matrix.os, 'windows') != true run: | conda install --yes pythonocc-core - python3 -m pip install --upgrade pip - python3 -m pip install smithers[vtk] - python3 -m pip install .[test] + python -m pip install --upgrade pip + python -m pip install smithers[vtk] + python -m pip install .[test] - name: Install Python dependencies on Windows if: startsWith(matrix.os, 'windows') @@ -53,4 +53,4 @@ jobs: - name: Test with pytest on Linux/MacOS if: startsWith(matrix.os, 'windows') != true - run: python3 -m pytest + run: python -m pytest From 9ecb750400c1516f09a33e9b12f3df6f2289b1c8 Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Thu, 6 Mar 2025 17:49:53 +0100 Subject: [PATCH 07/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index a45056d..64e20e7 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -30,6 +30,7 @@ jobs: auto-update-conda: true channels: conda-forge,defaults python-version: ${{ matrix.python-version }} + activate-environment: occ - name: Install Python dependencies on Linux/MacOS if: startsWith(matrix.os, 'windows') != true @@ -38,6 +39,7 @@ jobs: python -m pip install --upgrade pip python -m pip install smithers[vtk] python -m pip install .[test] + python -c 'import OCC' - name: Install Python dependencies on Windows if: startsWith(matrix.os, 'windows') From c080c28f36239f49fe2c709c4ea4f049f1a1106c Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Thu, 6 Mar 2025 18:07:21 +0100 Subject: [PATCH 08/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index 64e20e7..ee6ec09 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -27,8 +27,7 @@ jobs: - name: Setup Conda uses: conda-incubator/setup-miniconda@v3 with: - auto-update-conda: true - channels: conda-forge,defaults + channels: conda-forge, defaults python-version: ${{ matrix.python-version }} activate-environment: occ From 645c0ec092e0146069b47f5231f4e4fb3b7fb4ab Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Thu, 6 Mar 2025 18:19:58 +0100 Subject: [PATCH 09/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index ee6ec09..4e4b4f3 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -28,13 +28,13 @@ jobs: uses: conda-incubator/setup-miniconda@v3 with: channels: conda-forge, defaults - python-version: ${{ matrix.python-version }} - activate-environment: occ + activate-environment: "" - name: Install Python dependencies on Linux/MacOS if: startsWith(matrix.os, 'windows') != true run: | - conda install --yes pythonocc-core + conda create -n occ python=${{ matrix.python-version }} pythonocc-core + conda activate occ python -m pip install --upgrade pip python -m pip install smithers[vtk] python -m pip install .[test] From 53794bcb2b95581c21e35cfd6d83e3fb74650311 Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Mon, 10 Mar 2025 11:33:40 +0100 Subject: [PATCH 10/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index 4e4b4f3..c03edd7 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -31,10 +31,13 @@ jobs: activate-environment: "" - name: Install Python dependencies on Linux/MacOS + shell: bash -el {0} if: startsWith(matrix.os, 'windows') != true run: | conda create -n occ python=${{ matrix.python-version }} pythonocc-core + conda info conda activate occ + conda info python -m pip install --upgrade pip python -m pip install smithers[vtk] python -m pip install .[test] From 3660ec7e197279351d8a7c3340fa8ea90d5a7abb Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Mon, 10 Mar 2025 11:52:17 +0100 Subject: [PATCH 11/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index c03edd7..1af96da 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -56,5 +56,6 @@ jobs: run: python -m pytest - name: Test with pytest on Linux/MacOS + shell: bash -el {0} if: startsWith(matrix.os, 'windows') != true run: python -m pytest From 71e7b52f27fb893d5a712601efb5dccbda64a72f Mon Sep 17 00:00:00 2001 From: Nicola Demo Date: Mon, 10 Mar 2025 12:00:44 +0100 Subject: [PATCH 12/13] Update testing_pr.yml --- .github/workflows/testing_pr.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index 1af96da..8221e4f 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -58,4 +58,6 @@ jobs: - name: Test with pytest on Linux/MacOS shell: bash -el {0} if: startsWith(matrix.os, 'windows') != true - run: python -m pytest + run: | + conda activate occ + python -m pytest From b94fe89a1eb80c8deb4b47093415356ea8765146 Mon Sep 17 00:00:00 2001 From: Giulio Ortali Date: Tue, 15 Apr 2025 15:46:10 +0200 Subject: [PATCH 13/13] added test check modified props --- tests/test_blade.py | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/test_blade.py b/tests/test_blade.py index f24f8a2..ac85a33 100644 --- a/tests/test_blade.py +++ b/tests/test_blade.py @@ -835,3 +835,63 @@ def test_blade_str_method(self): string += '\nInduced rake from skew (in unit length)'\ ' for the sections = {}'.format(blade.induced_rake) assert blade.__str__() == string + + def test_blade_parameters_unchanged_after_transformations_and_rotation(self): + """Test that blade parameters remain unchanged after transformations and rotation.""" + # Create the original parameters + sections = np.asarray([NacaProfile(digits='0012') for i in range(10)]) + radii = np.arange(0.4, 1.31, 0.1) + chord_lengths = np.concatenate((np.arange(0.55, 1.1, 0.15), + np.arange(1.03, 0.9, -0.03), + np.array([0.3]))) + pitch = np.append(np.arange(3.0, 4., 0.2), np.arange(4.1, 3.2, -0.2)) + rake = np.append(np.arange(5e-3, 0.08, 1e-2), np.arange(0.075, 0.02, -3e-2)) + skew_angles = np.append(np.arange(-4., -9., -3.), np.arange(-7., 15., 3.)) + + # Store original section data + original_sections = [] + for section in sections: + original_sections.append({ + 'xup': section.xup_coordinates.copy(), + 'yup': section.yup_coordinates.copy(), + 'xdown': section.xdown_coordinates.copy(), + 'ydown': section.ydown_coordinates.copy() + }) + + # Build the blade + blade = bl.Blade( + sections=sections, + radii=radii, + chord_lengths=chord_lengths, + pitch=pitch, + rake=rake, + skew_angles=skew_angles) + + # Apply transformations and rotate 180 degrees around z-axis + blade.apply_transformations() + blade.rotate(deg_angle=180) + + # Verify parameters are unchanged + for i, section in enumerate(blade.sections): + np.testing.assert_array_equal( + section.xup_coordinates, + original_sections[i]['xup'] + ) + np.testing.assert_array_equal( + section.yup_coordinates, + original_sections[i]['yup'] + ) + np.testing.assert_array_equal( + section.xdown_coordinates, + original_sections[i]['xdown'] + ) + np.testing.assert_array_equal( + section.ydown_coordinates, + original_sections[i]['ydown'] + ) + + np.testing.assert_array_equal(blade.radii, radii) + np.testing.assert_array_equal(blade.chord_lengths, chord_lengths) + np.testing.assert_array_equal(blade.pitch, pitch) + np.testing.assert_array_equal(blade.rake, rake) + np.testing.assert_array_equal(blade.skew_angles, skew_angles)