Skip to content

Commit 840f365

Browse files
committed
fix issues
1 parent 3570713 commit 840f365

File tree

4 files changed

+36
-286
lines changed

4 files changed

+36
-286
lines changed

bladex/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
'ProfileInterface', 'NacaProfile', 'CustomProfile',
66
'ReversePropeller', 'Blade', 'Shaft', 'CylinderShaft',
77
'Propeller', 'Deformation', 'ParamFile', 'RBF',
8-
'reconstruct_f', 'scipy_bspline'
8+
'reconstruct_f', 'scipy_bspline', 'InterpolatedFace'
99
]
1010

1111
from .profile import ProfileInterface

bladex/blade.py

Lines changed: 27 additions & 259 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import matplotlib.pyplot as plt
66
from mpl_toolkits.mplot3d import Axes3D
77

8+
from .intepolatedface import InterpolatedFace
9+
810
class Blade(object):
911
"""
1012
Bottom-up parametrized blade construction.
@@ -158,16 +160,7 @@ def __init__(self, sections, radii, chord_lengths, pitch, rake,
158160
self.skew_angles = skew_angles
159161
self._check_params()
160162

161-
self.pitch_angles = self._compute_pitch_angle()
162-
self.induced_rake = self._induced_rake_from_skew()
163-
164-
self.blade_coordinates_up = []
165-
self.blade_coordinates_down = []
166-
167-
self.generated_upper_face = None
168-
self.generated_lower_face = None
169-
self.generated_tip = None
170-
self.generated_root = None
163+
self.reset()
171164

172165
def reset(self):
173166
"""
@@ -176,12 +169,12 @@ def reset(self):
176169
self.blade_coordinates_up = []
177170
self.blade_coordinates_down = []
178171

179-
self.generated_upper_face = None
180-
self.generated_lower_face = None
181-
self.generated_tip = None
182-
self.generated_root = None
172+
self.upper_face = None
173+
self.lower_face = None
174+
self.tip_face = None
175+
self.root_face = None
183176

184-
def build(self):
177+
def build(self, reflect=True):
185178
"""
186179
Generate a bottom-up constructed propeller blade without applying any
187180
transformations on the airfoils.
@@ -190,11 +183,17 @@ def build(self):
190183
the given 3D coordinates of the blade sections.
191184
192185
"""
193-
from . import InterpolatedFace
194-
upper_face = InterpolatedFace(self.blade_coordinates_up)
195-
lower_face = InterpolatedFace(self.blade_coordinates_down)
196-
tip_face = InterpolatedFace(np.stack
197-
186+
self.apply_transformations(reflect=reflect)
187+
self.upper_face = InterpolatedFace(self.blade_coordinates_up).face
188+
self.lower_face = InterpolatedFace(self.blade_coordinates_down).face
189+
self.tip_face = InterpolatedFace(np.stack([
190+
self.blade_coordinates_up[-1],
191+
self.blade_coordinates_down[-1]
192+
])).face
193+
self.root_face = InterpolatedFace(np.stack([
194+
self.blade_coordinates_up[0],
195+
self.blade_coordinates_down[0]
196+
])).face
198197

199198
def _check_params(self):
200199
"""
@@ -221,7 +220,7 @@ def _check_params(self):
221220
'rake, skew_angles} do not have the same shape.')
222221

223222
@property
224-
def pitch_angle(self):
223+
def pitch_angles(self):
225224
"""
226225
Return the pitch angle from the linear pitch for all blade sections.
227226
@@ -385,7 +384,7 @@ def rotate(self, deg_angle=None, rad_angle=None, axis='x'):
385384
or if neither is inserted
386385
387386
"""
388-
if not self.blade_coordinates_up:
387+
if len(self.blade_coordinates_up) == 0:
389388
raise ValueError('You must apply transformations before rotation.')
390389

391390
# Check rotation angle
@@ -431,10 +430,6 @@ def scale(self, factor):
431430
432431
:param float factor: scaling factor
433432
"""
434-
435-
scaling_matrix = np.array([factor, 0, 0, 0, factor,
436-
0, 0, 0, factor]).reshape((3, 3))
437-
438433
self.blade_coordinates_up *= factor
439434
self.blade_coordinates_down *= factor
440435

@@ -633,112 +628,6 @@ def _write_blade_errors(self, upper_face, lower_face, errors):
633628
output_string += '\n'
634629
f.write(output_string)
635630

636-
def generate_iges(self,
637-
upper_face=None,
638-
lower_face=None,
639-
tip=None,
640-
root=None,
641-
max_deg=1,
642-
display=False,
643-
errors=None):
644-
"""
645-
Generate and export the .iges CAD for the blade upper face, lower face,
646-
tip and root. This method requires PythonOCC (7.4.0) to be installed.
647-
648-
:param string upper_face: if string is passed then the method generates
649-
the blade upper surface using the BRepOffsetAPI_ThruSections
650-
algorithm, then exports the generated CAD into .iges file holding
651-
the name <upper_face_string>.iges. Default value is None
652-
:param string lower_face: if string is passed then the method generates
653-
the blade lower surface using the BRepOffsetAPI_ThruSections
654-
algorithm, then exports the generated CAD into .iges file holding
655-
the name <lower_face_string>.iges. Default value is None
656-
:param string tip: if string is passed then the method generates
657-
the blade tip using the BRepOffsetAPI_ThruSections algorithm
658-
in order to close the blade at the tip, then exports the generated
659-
CAD into .iges file holding the name <tip_string>.iges.
660-
Default value is None
661-
:param string root: if string is passed then the method generates
662-
the blade root using the BRepOffsetAPI_ThruSections algorithm
663-
in order to close the blade at the root, then exports the generated
664-
CAD into .iges file holding the name <tip_string>.iges.
665-
Default value is None
666-
:param int max_deg: Define the maximal U degree of generated surface.
667-
Default value is 1
668-
:param bool display: if True, then display the generated CAD. Default
669-
value is False
670-
:param string errors: if string is passed then the method writes out
671-
the distances between each discrete point used to construct the
672-
blade and the nearest point on the CAD that is perpendicular to
673-
that point. Default value is None
674-
675-
We note that the blade object must have its radial sections be arranged
676-
in order from the blade root to the blade tip, so that generate_iges
677-
method can build the CAD surface that passes through the corresponding
678-
airfoils. Also to be able to identify and close the blade tip and root.
679-
"""
680-
681-
from OCC.Core.IGESControl import IGESControl_Writer
682-
from OCC.Display.SimpleGui import init_display
683-
684-
if max_deg <= 0:
685-
raise ValueError('max_deg argument must be a positive integer.')
686-
687-
if upper_face:
688-
self._check_string(filename=upper_face)
689-
self._generate_upper_face(max_deg=max_deg)
690-
# Write IGES
691-
iges_writer = IGESControl_Writer()
692-
iges_writer.AddShape(self.generated_upper_face)
693-
iges_writer.Write(upper_face + '.iges')
694-
695-
if lower_face:
696-
self._check_string(filename=lower_face)
697-
self._generate_lower_face(max_deg=max_deg)
698-
# Write IGES
699-
iges_writer = IGESControl_Writer()
700-
iges_writer.AddShape(self.generated_lower_face)
701-
iges_writer.Write(lower_face + '.iges')
702-
703-
if tip:
704-
self._check_string(filename=tip)
705-
self._generate_tip(max_deg=max_deg)
706-
# Write IGES
707-
iges_writer = IGESControl_Writer()
708-
iges_writer.AddShape(self.generated_tip)
709-
iges_writer.Write(tip + '.iges')
710-
711-
if root:
712-
self._check_string(filename=root)
713-
self._generate_root(max_deg=max_deg)
714-
# Write IGES
715-
iges_writer = IGESControl_Writer()
716-
iges_writer.AddShape(self.generated_root)
717-
iges_writer.Write(root + '.iges')
718-
719-
if errors:
720-
# Write out errors between discrete points and constructed faces
721-
self._check_string(filename=errors)
722-
self._check_errors(upper_face=upper_face, lower_face=lower_face)
723-
724-
self._write_blade_errors(
725-
upper_face=upper_face, lower_face=lower_face, errors=errors)
726-
727-
if display:
728-
display, start_display, add_menu, add_function_to_menu = init_display(
729-
)
730-
731-
## DISPLAY FACES
732-
if upper_face:
733-
display.DisplayShape(self.generated_upper_face, update=True)
734-
if lower_face:
735-
display.DisplayShape(self.generated_lower_face, update=True)
736-
if tip:
737-
display.DisplayShape(self.generated_tip, update=True)
738-
if root:
739-
display.DisplayShape(self.generated_root, update=True)
740-
start_display()
741-
742631
def generate_solid(self,
743632
max_deg=1,
744633
display=False,
@@ -766,145 +655,24 @@ def generate_solid(self,
766655
if max_deg <= 0:
767656
raise ValueError('max_deg argument must be a positive integer.')
768657

769-
self._generate_upper_face(max_deg=max_deg)
770-
771-
print(self.generated_upper_face)
772-
from . import InterpolatedFace
773-
upper_face = InterpolatedFace(self.blade_coordinates_up)
774-
lower_face = InterpolatedFace(self.blade_coordinates_down)
775-
tip_face = InterpolatedFace(np.stack([
776-
self.blade_coordinates_up[-1],
777-
self.blade_coordinates_down[-1]
778-
]))
779-
root_face = InterpolatedFace(np.stack([
780-
self.blade_coordinates_up[0],
781-
self.blade_coordinates_down[0]
782-
]))
783-
# print(upper_face.face)
784-
# fff
785-
# self._generate_lower_face(max_deg=max_deg)
786-
# self._generate_tip(max_deg=max_deg)
787-
# self._generate_root(max_deg=max_deg)
788-
789-
if errors:
790-
# Write out errors between discrete points and constructed faces
791-
self._check_string(filename=errors)
792-
self._check_errors(upper_face=upper_face, lower_face=lower_face)
793-
794-
self._write_blade_errors(
795-
upper_face=upper_face, lower_face=lower_face, errors=errors)
796-
658+
faces = [
659+
self.upper_face, self.lower_face, self.tip_face, self.root_face
660+
]
797661

798662
sewer = BRepBuilderAPI_Sewing(1e-2)
799-
for face in [upper_face.face, lower_face.face, tip_face.face,
800-
root_face.face]:
663+
for face in faces:
801664
sewer.Add(face)
802665
sewer.Perform()
803666

804667
result_shell = sewer.SewedShape()
805668
solid_maker = BRepBuilderAPI_MakeSolid()
806669
solid_maker.Add(OCC.Core.TopoDS.topods.Shell(result_shell))
670+
807671
if not solid_maker.IsDone():
808672
raise RuntimeError('Unsuccessful assembling of solid blade')
809673
result_solid = solid_maker.Solid()
810-
return result_solid
811-
812-
def generate_stl(self, upper_face=None,
813-
lower_face=None,
814-
tip=None,
815-
root=None,
816-
max_deg=1,
817-
display=False,
818-
errors=None):
819-
"""
820-
Generate and export the .STL files for upper face, lower face, tip
821-
and root. This method requires PythonOCC (7.4.0) to be installed.
822-
823-
:param string upper_face: if string is passed then the method generates
824-
the blade upper surface using the BRepOffsetAPI_ThruSections
825-
algorithm, then exports the generated CAD into .stl file holding
826-
the name <upper_face_string>.stl. Default value is None
827-
:param string lower_face: if string is passed then the method generates
828-
the blade lower surface using the BRepOffsetAPI_ThruSections
829-
algorithm, then exports the generated CAD into .stl file holding
830-
the name <lower_face_string>.stl. Default value is None
831-
:param string tip: if string is passed then the method generates
832-
the blade tip using the BRepOffsetAPI_ThruSections algorithm
833-
in order to close the blade at the tip, then exports the generated
834-
CAD into .stl file holding the name <tip_string>.stl.
835-
Default value is None
836-
:param string root: if string is passed then the method generates
837-
the blade root using the BRepOffsetAPI_ThruSections algorithm
838-
in order to close the blade at the root, then exports the generated
839-
CAD into .stl file holding the name <tip_string>.stl.
840-
Default value is None
841-
:param int max_deg: Define the maximal U degree of generated surface.
842-
Default value is 1
843-
:param bool display: if True, then display the generated CAD. Default
844-
value is False
845-
:param string errors: if string is passed then the method writes out
846-
the distances between each discrete point used to construct the
847-
blade and the nearest point on the CAD that is perpendicular to
848-
that point. Default value is None
849-
850-
We note that the blade object must have its radial sections be arranged
851-
in order from the blade root to the blade tip, so that generate_stl
852-
method can build the CAD surface that passes through the corresponding
853-
airfoils. Also to be able to identify and close the blade tip and root.
854-
"""
855-
856-
from OCC.Extend.DataExchange import write_stl_file
857-
from OCC.Display.SimpleGui import init_display
858-
859-
if max_deg <= 0:
860-
raise ValueError('max_deg argument must be a positive integer.')
861674

862-
if upper_face:
863-
self._check_string(filename=upper_face)
864-
self._generate_upper_face(max_deg=max_deg)
865-
# Write STL
866-
write_stl_file(self.generated_upper_face, upper_face + '.stl')
867-
868-
if lower_face:
869-
self._check_string(filename=lower_face)
870-
self._generate_lower_face(max_deg=max_deg)
871-
# Write STL
872-
write_stl_file(self.generated_lower_face, lower_face + '.stl')
873-
874-
if tip:
875-
self._check_string(filename=tip)
876-
self._generate_tip(max_deg=max_deg)
877-
# Write STL
878-
write_stl_file(self.generated_tip, tip + '.stl')
879-
880-
if root:
881-
self._check_string(filename=root)
882-
self._generate_root(max_deg=max_deg)
883-
# Write STL
884-
write_stl_file(self.generated_root, root + '.stl')
885-
886-
if errors:
887-
# Write out errors between discrete points and constructed faces
888-
self._check_string(filename=errors)
889-
self._check_errors(upper_face=upper_face, lower_face=lower_face)
890-
891-
self._write_blade_errors(
892-
upper_face=upper_face, lower_face=lower_face, errors=errors)
893-
894-
if display:
895-
display, start_display, add_menu, add_function_to_menu = init_display(
896-
)
897-
898-
## DISPLAY FACES
899-
if upper_face:
900-
display.DisplayShape(self.generated_upper_face, update=True)
901-
if lower_face:
902-
display.DisplayShape(self.generated_lower_face, update=True)
903-
if tip:
904-
display.DisplayShape(self.generated_tip, update=True)
905-
if root:
906-
display.DisplayShape(self.generated_root, update=True)
907-
start_display()
675+
return result_solid
908676

909677
def generate_stl_blade(self, filename):
910678
"""

bladex/profile/customprofile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
"""
99

1010
import numpy as np
11-
from .profileinterface import ProfileInterface
11+
from .baseprofile import BaseProfile
1212

1313

14-
class CustomProfile(ProfileInterface):
14+
class CustomProfile(BaseProfile):
1515
"""
1616
Provide custom profile, given the airfoil coordinates or the airfoil
1717
parameters, i.e. , chord percentages and length, nondimensional and

0 commit comments

Comments
 (0)