diff --git a/bladex/blade.py b/bladex/blade.py index ed5b476..161c666 100644 --- a/bladex/blade.py +++ b/bladex/blade.py @@ -711,7 +711,7 @@ def generate_solid(self): self.upper_face, self.lower_face, self.tip_face, self.root_face ] - sewer = BRepBuilderAPI_Sewing(1e-2) + sewer = BRepBuilderAPI_Sewing(1e-7) for face in faces: sewer.Add(face) sewer.Perform() diff --git a/bladex/intepolatedface.py b/bladex/intepolatedface.py index 045a1bf..df40a06 100644 --- a/bladex/intepolatedface.py +++ b/bladex/intepolatedface.py @@ -14,7 +14,7 @@ class InterpolatedFace: - def __init__(self, pts, max_deg=3, tolerance=1e-10): + def __init__(self, pts, max_deg=1, tolerance=1e-6): print(pts.shape) if pts.ndim not in [2, 3]: diff --git a/bladex/propeller.py b/bladex/propeller.py index 868c737..9a4e09c 100644 --- a/bladex/propeller.py +++ b/bladex/propeller.py @@ -10,6 +10,21 @@ from smithers.io.obj import ObjHandler, WavefrontOBJ from smithers.io.stlhandler import STLHandler +from OCC.Core.BRep import BRep_Builder +from OCC.Core.TopoDS import TopoDS_Compound +import copy + +def make_compound(shapes): + builder = BRep_Builder() + comp = TopoDS_Compound() + builder.MakeCompound(comp) + + for s in shapes: + if s is None: + raise ValueError("make_compound: shape is None") + builder.Add(comp, s) + + return comp class Propeller(object): """ @@ -23,11 +38,10 @@ class Propeller(object): :cvar OCC.Core.TopoDS.TopoDS_Shell sewed_full_body: propeller with shaft shell """ - def __init__(self, shaft, blade, n_blades): - self.shaft_solid = shaft.generate_solid() + def __init__(self, shaft, blade, n_blades, reflect_blade=False): + self.shaft = shaft - blade.build(reflect=True) - import copy + blade.build(reflect=reflect_blade) self.blades = [copy.deepcopy(blade) for _ in range(n_blades)] [ @@ -35,35 +49,74 @@ def __init__(self, shaft, blade, n_blades): for i, blade in enumerate(self.blades) ] - blade_solid = blade.generate_solid() - blades = [] - blades.append(blade_solid) - for i in range(n_blades - 1): - blade.rotate(rad_angle=1.0 * 2.0 * np.pi / float(n_blades)) - blade_solid = blade.generate_solid() - blades.append(blade_solid) - blade_solids = [blade_.generate_solid() for blade_ in self.blades] - blades_combined = blade_solids[0] - for i in range(len(blades) - 1): - print(i) - boolean_union = BRepAlgoAPI_Fuse(blades_combined, blade_solids[i + 1]) - boolean_union.Build() - if not boolean_union.IsDone(): - raise RuntimeError("Unsuccessful assembling of blade") - blades_combined = boolean_union.Shape() - self.blades_solid = blades_combined - - boolean_union = BRepAlgoAPI_Fuse(self.shaft_solid, blades_combined) - boolean_union.Build() - result_compound = boolean_union.Shape() + def tmp_stl(self, filename, linear_deflection=0.1): + """ + + """ + from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh + from OCC.Core.StlAPI import StlAPI_Writer + shapes = [] + for blade_ in self.blades: + + sewer = BRepBuilderAPI_Sewing(1e-2) + sewer.Add(blade_.upper_face) + sewer.Add(blade_.lower_face) + sewer.Add(blade_.root_face) + sewer.Add(blade_.tip_face) + sewer.Perform() + sewed_shape = sewer.SewedShape() + shapes.append(sewed_shape) + + blades_compound = make_compound(shapes) + triangulation = BRepMesh_IncrementalMesh(blades_compound, linear_deflection, True) + triangulation.Perform() + + writer = StlAPI_Writer() + writer.SetASCIIMode(False) + writer.Write(blades_compound, filename) + + @property + def shape(self): + if hasattr(self, '_shape'): + return self._shape + + solid = self.solid sewer = BRepBuilderAPI_Sewing(1e-2) - sewer.Add(result_compound) + sewer.Add(solid) sewer.Perform() - self.sewed_full_body = sewer.SewedShape() + + self._shape = sewer.SewedShape() + return self._shape + + @property + def solid(self): + """ + Docstring for build + + :param self: Description + """ + if hasattr(self, '_solid'): + return self._solid + + shaft_solid = self.shaft.generate_solid() + blade_solids = [blade_.generate_solid() for blade_ in self.blades] + blades_compound = make_compound(blade_solids) + + fuse = BRepAlgoAPI_Fuse(shaft_solid, blades_compound) + # fuse.SetRunParallel(True) # if available in your build + fuse.SetFuzzyValue(1e-4) + + fuse.Build() + if not fuse.IsDone(): + raise RuntimeError("Fuse shaft + blades failed") + + self._solid = fuse.Shape() + return self._solid + - def generate_iges(self, filename): + def export_iges(self, filename): """ Export the .iges CAD for the propeller with shaft. @@ -73,10 +126,10 @@ def generate_iges(self, filename): completed successfully """ iges_writer = IGESControl_Writer() - iges_writer.AddShape(self.sewed_full_body) + iges_writer.AddShape(self.shape) iges_writer.Write(filename) - def generate_stl(self, filename): + def export_stl(self, filename): """ Export the .stl CAD for the propeller with shaft. @@ -85,7 +138,7 @@ def generate_stl(self, filename): :raises RuntimeError: if the solid assembling of blades is not completed successfully """ - write_stl_file(self.sewed_full_body, filename) + write_stl_file(self.shape, filename) def generate_obj(self, filename, region_selector="by_coords", **kwargs): """ @@ -254,5 +307,5 @@ def display(self): Display the propeller with shaft. """ display, start_display = init_display()[:2] - display.DisplayShape(self.sewed_full_body, update=True) + display.DisplayShape(self.shape, update=True) start_display() \ No newline at end of file