def _TransformAirfoil(self): """Given a normal airfoil, nose in origin, chord along x axis, applies rotations, translation and (soon) smoothing """ # TODO: Smoothing # for i in range(self.SmoothingIterations): # rs.FairCurve(self.Curve) # Can assume that the chord is from 0,0,0 to 1,0,0 before translation h_ChordLine = GC_MakeSegment(gp_Pnt(0, 0, 0), gp_Pnt(1, 0, 0)).Value() ChordLine = h_ChordLine.GetObject() Curve = self.Curve.GetObject() # Scaling: Curve.Scale(gp_Pnt(0, 0, 0), self.ChordLength) ChordLine.Scale(gp_Pnt(0, 0, 0), self.ChordLength) # Rotations - Note that direction is opposite to Rhino # Dihedral: if self.Rotation: Curve.Rotate(gp_OX(), np.radians(self.Rotation)) ChordLine.Rotate(gp_OX(), np.radians(self.Rotation)) # Twist: if self.Twist: Curve.Rotate(gp_OY(), -np.radians(self.Twist)) ChordLine.Rotate(gp_OY(), -np.radians(self.Twist)) # Translation: # self.Curve = Handle_Geom_BSplineCurve_DownCast(Curve.Translated( # gp_Vec(*self.LE)) # ) Curve.Translate(gp_Vec(*self.LE)) ChordLine.Translate(gp_Vec(*self.LE)) self.ChordLine = ChordLine.GetHandle() return None
def rotate_shp_3_axis(shape, rx, ry, rz, unity="deg"): """ Rotate a shape around (O,x), (O,y) and (O,z). @param rx_degree : rotation around (O,x) @param ry_degree : rotation around (O,y) @param rz_degree : rotation around (O,z) @return : the rotated shape. """ if unity == "deg": # convert angle to radians rx = radians(rx) ry = radians(ry) rz = radians(rz) alpha = gp_Trsf() alpha.SetRotation(gp_OX(), rx) beta = gp_Trsf() beta.SetRotation(gp_OY(), ry) gamma = gp_Trsf() gamma.SetRotation(gp_OZ(), rz) brep_trns = BRepBuilderAPI_Transform(shape, alpha*beta*gamma, False) shp = brep_trns.Shape() return shp
lim_coord1 = (xmin, xmax) lim_coord2 = (ymin, ymax) section_height = zmax - 0.18 # A horizontal plane is created from which a face is constructed to intersect with # the building. The face is transparently displayed along with the building. section_plane = gp_Pln(gp_Pnt(0, 0, section_height), gp_Dir(0, 0, 1)) section_face = BRepBuilderAPI_MakeFace(section_plane, xmin, xmax, ymin, ymax).Face() plt.figure() plt.xlim(lim_coord1) plt.ylim(lim_coord2) # Quick way to specify the Y axis xAxis = gp_OY() # Set up the mirror aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) # Explore the faces of the shape (these are known to be named) exp = TopExp_Explorer(shape, TopAbs_FACE) while exp.More(): s = exp.Current() tp = Topo(s) for face in tp.faces(): section = BRepAlgoAPI_Section(section_face, face).Shape() # Apply the mirror transformation
def BuildTurbofanNacelle(self): """ The defaults yield a nacelle similar to that of an RR Trent 1000 / GEnx #TODO: break this down into modular function calls """ CentreLocation = self.CentreLocation MeanNacelleLength = self.MeanNacelleLength HighlightRadius = self.HighlightRadius HighlightDepth = 0.12 * self.MeanNacelleLength SectionNo = 100 # Draw the nacelle with centre of the intake highlight circle in 0,0,0 HHighlight = act.make_circle3pt([0, 0, HighlightRadius], [0, -HighlightRadius, 0], [0, 0, -HighlightRadius]) Highlight = HHighlight.GetObject() HHighlightCutterCircle = \ act.make_circle3pt([0, 0, HighlightRadius * 1.5], [0, -HighlightRadius * 1.5, 0], [0, 0, -HighlightRadius * 1.5]) HighlightCutterCircle = HHighlightCutterCircle.GetObject() # Fan disk for CFD boundary conditions FanCircle = Handle_Geom_Circle.DownCast( Highlight.Translated(gp_Vec(MeanNacelleLength * 0.25, 0, 0))) wire = act.make_wire(act.make_edge(FanCircle)) FanDisk = act.make_face(wire) self.AddComponent(FanDisk, 'FanDisk') # Aft outflow for CFD boundary conditions BypassCircle = Handle_Geom_Circle.DownCast( Highlight.Translated(gp_Vec(MeanNacelleLength * 0.85, 0, 0))) wire = act.make_wire(act.make_edge(BypassCircle)) BypassDisk = act.make_face(wire) self.AddComponent(BypassDisk, 'BypassDisk') # Outflow cone TailConeBasePoint = np.array([MeanNacelleLength * 0.84, 0, 0]) TailConeHeight = MeanNacelleLength * (1.35 - 0.84) TailConeRadius = HighlightRadius * 0.782 TailCone = act.AddCone(TailConeBasePoint, TailConeRadius, TailConeHeight) self.AddComponent(TailCone, 'TailCone') # Spinner cone SpinnerConeBasePoint = np.array([MeanNacelleLength * 0.26, 0, 0]) SpinnerConeHeight = MeanNacelleLength * (0.26 - 0.08) SpinnerConeRadius = MeanNacelleLength * 0.09 Spinner = act.AddCone(SpinnerConeBasePoint, SpinnerConeRadius, SpinnerConeHeight, direction=gp_Dir(-1, 0, 0)) self.AddComponent(Spinner, 'Spinner') # # Tilt the intake RotAx = gp_OY() Highlight.Rotate(RotAx, np.radians(self.ScarfAngle)) # # Set up the disk for separating the intake lip later HighlightCutterCircle.Rotate(RotAx, np.radians(self.ScarfAngle)) HighlightCutterDisk = act.PlanarSurf(HighlightCutterCircle) HighlightCutterDisk =\ act.translate_topods_from_vector(HighlightCutterDisk, gp_Vec(HighlightDepth, 0, 0)) # Build the actual airfoil sections to define the nacelle HighlightPointVector = act.Uniform_Points_on_Curve( Highlight.GetHandle(), SectionNo) Sections = [] TailPoints = [] Twist = 0 AirfoilSeligName = 'goe613' Rotations = np.linspace(0, 360, SectionNo) for i, pt in enumerate(HighlightPointVector): AfChord = MeanNacelleLength - pt.X() Af = primitives.Airfoil([pt.X(), pt.Y(), pt.Z()], AfChord, Rotations[i], Twist, SeligProfile=AirfoilSeligName).Curve Sections.append(Af) TailPoints.append(Af.GetObject().EndPoint()) self._sections = Sections # # Build the actual nacelle OML surface # EndCircle = act.points_to_bspline(TailPoints) #Dont need this? # self._EndCircle = EndCircle Nacelle = act.AddSurfaceLoft(Sections) self.AddComponent(Nacelle, 'Nacelle') # TODO: Separate the lip # Cowling, HighlightSection = act.TrimShapebyPlane(Nacelle, # HighlightCutterDisk, # True) # Move the engine into its actual place on the wing self.TranslateComponents(gp_Vec(*CentreLocation)) # Now build the pylon between the engine and the chord on the wing CP1 = gp_Pnt(MeanNacelleLength * 0.26 + CentreLocation[0], CentreLocation[1], CentreLocation[2] + HighlightRadius * 0.1) CP2 = gp_Pnt(MeanNacelleLength * 0.4 + CentreLocation[0], CentreLocation[1], HighlightRadius * 1.45 + CentreLocation[2]) # Get the chord from its handle Chord = self.HChord.GetObject() CP3 = Chord.EndPoint() CP4 = Chord.StartPoint() self._pylonPts = [CP1, CP2, CP3, CP4] # Pylon wireframe tangents = np.array([[0, 0, 1], [1, 0, 0]]) PylonTop = act.points_to_bspline([CP1, CP2, CP3, CP4], tangents=tangents) self._PylonTop = PylonTop PylonBase_LE = [CP1.X(), CP1.Y(), CP1.Z()] PylonAf = primitives.Airfoil(PylonBase_LE, MeanNacelleLength * 1.35, 90, 0, Naca4Profile='0012', EnforceSharpTE=False) self._PylonAf = PylonAf LowerTE = PylonAf.ChordLine.GetObject().EndPoint() # LowerTE = rs.CurveEndPoint(PylonChord) PylonTE = GC_MakeSegment(LowerTE, CP4).Value() self._PylonTE = PylonTE edges = [act.make_edge(PylonAf.ChordLine), act.make_edge(PylonTop), act.make_edge(PylonTE)] Pylon_symplane = act.make_face(act.make_wire(*edges)) self.AddComponent(Pylon_symplane, 'Pylon_symplane') # TODO: Pylon surface. Currently a flat plate at symmetry plane. # This should be done with a plate surface (similar to NetworkSrf in # Rhino), but I haven't got this to work yet # Method 1: Sweep - gives the wrong shape # Pylon_tip = GC_MakeCircle(gp_Ax1(CP4, gp_Dir(0, 1, 0)), # PylonAf.ChordLength*0.001 # ).Value() # # Pylon_curve = PylonAf.Curve.GetObject() # PylonAf_TE = act.make_edge(Pylon_curve.StartPoint(), # Pylon_curve.EndPoint()) # PylonAf_Face = act.PlanarSurf(PylonAf.Curve) # PylonAf_closedwire = act.make_wire(act.make_edge(PylonAf.Curve), # PylonAf_TE) # sections = [PylonAf.Curve, PylonTE] # spine = act.make_wire(act.make_edge(PylonTop)) # self.PylonLeft = act.make_pipe_shell(spine, sections) # # Move into place under the wing # self._Translate(gp_Vec(0,-CentreLocation[1],0)) # # TODO: Mirror the pylon half surface # PylonRight = act.mirror(PylonLeft, plane='xz') # PylonAfCurve = act.AddTEtoOpenAirfoil(PylonAfCurve) # PylonAfSrf = rs.AddPlanarSrf(PylonAfCurve) return None
def BuildTurbofanNacelle(self): """ The defaults yield a nacelle similar to that of an RR Trent 1000 / GEnx #TODO: break this down into modular function calls """ CentreLocation = self.CentreLocation MeanNacelleLength = self.MeanNacelleLength HighlightRadius = self.HighlightRadius HighlightDepth = 0.12 * self.MeanNacelleLength SectionNo = 100 # Draw the nacelle with centre of the intake highlight circle in 0,0,0 HHighlight = act.make_circle3pt([0, 0, HighlightRadius], [0, -HighlightRadius, 0], [0, 0, -HighlightRadius]) Highlight = HHighlight.GetObject() HHighlightCutterCircle = \ act.make_circle3pt([0, 0, HighlightRadius * 1.5], [0, -HighlightRadius * 1.5, 0], [0, 0, -HighlightRadius * 1.5]) HighlightCutterCircle = HHighlightCutterCircle.GetObject() # Fan disk for CFD boundary conditions FanCircle = Handle_Geom_Circle.DownCast( Highlight.Translated(gp_Vec(MeanNacelleLength * 0.25, 0, 0))) wire = act.make_wire(act.make_edge(FanCircle)) FanDisk = act.make_face(wire) self.AddComponent(FanDisk, 'FanDisk') # Aft outflow for CFD boundary conditions BypassCircle = Handle_Geom_Circle.DownCast( Highlight.Translated(gp_Vec(MeanNacelleLength * 0.85, 0, 0))) wire = act.make_wire(act.make_edge(BypassCircle)) BypassDisk = act.make_face(wire) self.AddComponent(BypassDisk, 'BypassDisk') # Outflow cone TailConeBasePoint = np.array([MeanNacelleLength * 0.84, 0, 0]) TailConeHeight = MeanNacelleLength * (1.35 - 0.84) TailConeRadius = HighlightRadius * 0.782 TailCone = act.AddCone(TailConeBasePoint, TailConeRadius, TailConeHeight) self.AddComponent(TailCone, 'TailCone') # Spinner cone SpinnerConeBasePoint = np.array([MeanNacelleLength * 0.26, 0, 0]) SpinnerConeHeight = MeanNacelleLength * (0.26 - 0.08) SpinnerConeRadius = MeanNacelleLength * 0.09 Spinner = act.AddCone(SpinnerConeBasePoint, SpinnerConeRadius, SpinnerConeHeight, direction=gp_Dir(-1, 0, 0)) self.AddComponent(Spinner, 'Spinner') # # Tilt the intake RotAx = gp_OY() Highlight.Rotate(RotAx, np.radians(self.ScarfAngle)) # # Set up the disk for separating the intake lip later HighlightCutterCircle.Rotate(RotAx, np.radians(self.ScarfAngle)) HighlightCutterDisk = act.PlanarSurf(HighlightCutterCircle) HighlightCutterDisk =\ act.translate_topods_from_vector(HighlightCutterDisk, gp_Vec(HighlightDepth, 0, 0)) # Build the actual airfoil sections to define the nacelle HighlightPointVector = act.Uniform_Points_on_Curve( Highlight.GetHandle(), SectionNo) Sections = [] TailPoints = [] Twist = 0 AirfoilSeligName = 'goe613' Rotations = np.linspace(0, 360, SectionNo) for i, pt in enumerate(HighlightPointVector): AfChord = MeanNacelleLength - pt.X() Af = primitives.Airfoil([pt.X(), pt.Y(), pt.Z()], AfChord, Rotations[i], Twist, SeligProfile=AirfoilSeligName).Curve Sections.append(Af) TailPoints.append(Af.GetObject().EndPoint()) self._sections = Sections # # Build the actual nacelle OML surface # EndCircle = act.points_to_bspline(TailPoints) #Dont need this? # self._EndCircle = EndCircle Nacelle = act.AddSurfaceLoft(Sections) self.AddComponent(Nacelle, 'Nacelle') # TODO: Separate the lip # Cowling, HighlightSection = act.TrimShapebyPlane(Nacelle, # HighlightCutterDisk, # True) # Move the engine into its actual place on the wing self.TranslateComponents(gp_Vec(*CentreLocation)) # Now build the pylon between the engine and the chord on the wing CP1 = gp_Pnt(MeanNacelleLength * 0.26 + CentreLocation[0], CentreLocation[1], CentreLocation[2] + HighlightRadius * 0.1) CP2 = gp_Pnt(MeanNacelleLength * 0.4 + CentreLocation[0], CentreLocation[1], HighlightRadius * 1.45 + CentreLocation[2]) # Get the chord from its handle Chord = self.HChord.GetObject() CP3 = Chord.EndPoint() CP4 = Chord.StartPoint() self._pylonPts = [CP1, CP2, CP3, CP4] # Pylon wireframe tangents = np.array([[0, 0, 1], [1, 0, 0]]) PylonTop = act.points_to_bspline([CP1, CP2, CP3, CP4], tangents=tangents) self._PylonTop = PylonTop PylonBase_LE = [CP1.X(), CP1.Y(), CP1.Z()] PylonAf = primitives.Airfoil(PylonBase_LE, MeanNacelleLength * 1.35, 90, 0, Naca4Profile='0012', EnforceSharpTE=False) self._PylonAf = PylonAf LowerTE = PylonAf.ChordLine.GetObject().EndPoint() # LowerTE = rs.CurveEndPoint(PylonChord) PylonTE = GC_MakeSegment(LowerTE, CP4).Value() self._PylonTE = PylonTE edges = [ act.make_edge(PylonAf.ChordLine), act.make_edge(PylonTop), act.make_edge(PylonTE) ] Pylon_symplane = act.make_face(act.make_wire(*edges)) self.AddComponent(Pylon_symplane, 'Pylon_symplane') # TODO: Pylon surface. Currently a flat plate at symmetry plane. # This should be done with a plate surface (similar to NetworkSrf in # Rhino), but I haven't got this to work yet # Method 1: Sweep - gives the wrong shape # Pylon_tip = GC_MakeCircle(gp_Ax1(CP4, gp_Dir(0, 1, 0)), # PylonAf.ChordLength*0.001 # ).Value() # # Pylon_curve = PylonAf.Curve.GetObject() # PylonAf_TE = act.make_edge(Pylon_curve.StartPoint(), # Pylon_curve.EndPoint()) # PylonAf_Face = act.PlanarSurf(PylonAf.Curve) # PylonAf_closedwire = act.make_wire(act.make_edge(PylonAf.Curve), # PylonAf_TE) # sections = [PylonAf.Curve, PylonTE] # spine = act.make_wire(act.make_edge(PylonTop)) # self.PylonLeft = act.make_pipe_shell(spine, sections) # # Move into place under the wing # self._Translate(gp_Vec(0,-CentreLocation[1],0)) # # TODO: Mirror the pylon half surface # PylonRight = act.mirror(PylonLeft, plane='xz') # PylonAfCurve = act.AddTEtoOpenAirfoil(PylonAfCurve) # PylonAfSrf = rs.AddPlanarSrf(PylonAfCurve) return None