def test_project_curve_to_plane(): # Projects a line of length 1 from above the XOY plane, and tests points # on the resulting line from OCC.Geom import Geom_Plane, Geom_TrimmedCurve from OCC.GC import GC_MakeSegment from OCC.gp import gp_Ax3, gp_XOY, gp_Pnt, gp_Dir XOY = Geom_Plane(gp_Ax3(gp_XOY())) curve = GC_MakeSegment(gp_Pnt(0, 0, 5), gp_Pnt(1, 0, 5)).Value() direction = gp_Dir(0, 0, 1) Hproj_curve = act.project_curve_to_plane(curve, XOY.GetHandle(), direction) proj_curve = Hproj_curve.GetObject() # The start and end points of the curve p1 = proj_curve.Value(0) p2 = proj_curve.Value(1) p1_array = np.array([p1.X(), p1.Y(), p1.Z()]) p2_array = np.array([p2.X(), p2.Y(), p2.Z()]) # The expected start and end points start = np.array([0, 0, 0]) end = np.array([1, 0, 0]) # Assert that neither points have a Y or Z component, and that assert((np.all(p1_array == start) and np.all(p2_array == end)) or (np.all(p1_array == end) and np.all(p2_array == start)))
def _fitAirfoiltoPoints(self, x, z): """ Fits an OCC curve to airfoil x, z points Parameters ---------- x : array airfoil curve x points z : array airfoil curve z points Returns ------- spline_2d : OCC.Geom.Geom_BSplineCurve the generated spline """ N = len(x) y = [0. for i in xrange(N)] pnts = np.vstack([x, y, z]).T # periodic=False # tangents= Curve = act.points_to_bspline(pnts, True) # Saving the points for visualisation (need to remove this) self._points = [gp_Pnt(*pnt) for pnt in pnts] return Curve
def test_CalculateSurfaceArea(): """Use a few simple shapes to test the surface area function. Notes ----- This isnt testing the area building algorithm, just that my setup of the function works for a variety of different OCC objects - PChambers """ # A flat square edge lengths 1 from OCC.BRepBuilderAPI import BRepBuilderAPI_MakePolygon p1 = gp_Pnt(0, 0, 0) p2 = gp_Pnt(1, 0, 0) p3 = gp_Pnt(1, 1, 0) p4 = gp_Pnt(0, 1, 0) surf1 = act.make_face( BRepBuilderAPI_MakePolygon(p1, p2, p3, p4, True).Wire()) # The tolerance for difference between output and expected area tol = 1e-12 assert(np.abs(act.CalculateSurfaceArea(surf1) - 1) < tol) # A sphere with radius 1 from OCC.BRepPrimAPI import BRepPrimAPI_MakeSphere r = 1 # The tolerance need to be relaxed a bit for this case tol = 1e-04 sphere = BRepPrimAPI_MakeSphere(r).Shape() assert(np.abs(act.CalculateSurfaceArea(sphere) - 4 * np.pi * (r**2)) < tol)
def test_project_curve_to_surface(): """Returning object rather than handle from this function gave bugs between 0.16.3 and 0.16.5 - adding test to preempt future oddness""" # Edge to project: h = 5 pnts = np.array([[0, h, 0], [1, h, 2], [2, h, 3], [4, h, 3], [5, h, 5]]) spline = act.points_to_bspline(pnts) # Surface to project onto: from OCC.GC import GC_MakeCircle circle = GC_MakeCircle(gp_Pnt(0,0,0), gp_Dir(0, 1, 0), 10).Value() edge = act.make_edge(circle) face = act.make_face(act.make_wire(edge)) Hprojected_curve = act.project_curve_to_surface(spline, face, gp_Dir(0, -1, 0)) # Check that the curve created is not null check_valid_object(Hprojected_curve)
def test_points_to_bspline_nparray(): # This is just to check my function will succeed to create a bspline - # Hopefully PythonOCC tests will test the values of curves generated pnts = np.array([[0, 0, 0], [1, 0, 2], [2, 0, 3], [4, 0, 3], [5, 0, 5]]) spline = act.points_to_bspline(pnts) # test the curve is not null assert(not spline.IsNull()) # This will raise an error if the curve creation didn't work - don't need # to add an assert statement here o = spline.GetObject()
def test_coslin(): abscissa = act.coslin(0.5, 8, 8)[0] ans = np.array([0.0, 0.01253604390908819, 0.04951556604879043, 0.1090842587659851, 0.1882550990706332, 0.2830581304412209, 0.3887395330218428, 0.49999999999999994, 0.5625, 0.625, 0.6875, 0.75, 0.8125, 0.875, 0.9375, 1.0]) assert(np.all(np.abs(abscissa - ans) < 1e-10))
def _NACA4cambercurve(self, MaxCamberLocTenthChord, MaxCamberPercChord): """ Generates the camber curve of a NACA 4-digit airfoil Paramters --------- MaxCamberLocTenthChord : int MaxCamberPercChord : int Returns ------- """ # Using the original notation of Jacobs et al.(1933) xmc = MaxCamberLocTenthChord / 10.0 zcammax = MaxCamberPercChord / 100.0 # Protect against division by zero on airfoils like NACA0012 if xmc == 0: xmc = 0.2 # Sampling the chord line ChordCoord, NCosPoints = act.coslin(xmc) # Compute the two sections of the camber curve and its slope # zcam = [] # dzcamdx = [] cos_pts = ChordCoord[0:NCosPoints] lin_pts = ChordCoord[NCosPoints:] zcam = np.hstack(( (zcammax/(xmc ** 2)) * (2*xmc*cos_pts - cos_pts**2), (zcammax/((1-xmc)**2)) * \ (1-2*xmc+2*xmc*lin_pts-(lin_pts ** 2)) )) dzcamdx = np.hstack( ((zcammax / xmc**2) * (2 * xmc - 2 * cos_pts), (zcammax / (1 - xmc)**2) * (2 * xmc - 2 * lin_pts))) return ChordCoord, zcam, dzcamdx
def Rendering(obj): display, start_display, add_menu, add_function_to_menu = init_display() # Printing the variables from the aircraft object... # attrs = vars(aircraft) # pprint.pprint(attrs,width=1) #------------- WING -------------------- # Add NACA 4 digit airfoils to loft between: x0 = float(obj.geo['Kink_wing']['x'][0]) y0 = float(obj.geo['Kink_wing']['y'][0]) z0 = 0.0 c0 = float(obj.geo['Kink_wing']['chords'][0]) # z0 = obj.geo['Kink_wing']['zu'][0] x1 = float(obj.geo['Kink_wing']['x'][1]) y1 = float(obj.geo['Kink_wing']['y'][1]) z1 = 0.0 c1 = float(obj.geo['Kink_wing']['chords'][1]) # x2 = float(obj.geo['Kink_wing']['x'][2]) y2 = float(obj.geo['Kink_wing']['y'][2]) z2 = 0.0 c2 = float(obj.geo['Kink_wing']['chords'][2]) # x3 = float(obj.geo['Kink_wing']['x'][3]) y3 = float(obj.geo['Kink_wing']['y'][3]) z3 = 0.0 c3 = float(obj.geo['Kink_wing']['chords'][3]) # Profiles... Af0 = airconics.primitives.Airfoil([x0, y0, z0], ChordLength=c0, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af0.Curve, update=True, color='GREEN') Af1 = airconics.primitives.Airfoil([x1, y1, z1], ChordLength=c1, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af1.Curve, update=True, color='GREEN') Af2 = airconics.primitives.Airfoil([x2, y2, z2], ChordLength=c2, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af2.Curve, update=True, color='GREEN') Af3 = airconics.primitives.Airfoil([x3, y3, z3], ChordLength=c3, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af3.Curve, update=True, color='GREEN') surf_wingin = act.AddSurfaceLoft([Af0, Af1, Af2]) surf_wingout = act.AddSurfaceLoft([Af2, Af3]) #------------- HT -------------------- # Add NACA 4 digit airfoils to loft between: x0 = float(obj.geo['horz']['x'][0]) y0 = float(obj.geo['horz']['y'][0]) z0 = 0.0 c0 = float(obj.geo['horz']['chords'][0]) # z0 = obj.geo['Kink_wing']['zu'][0] x1 = float(obj.geo['horz']['x'][1]) y1 = float(obj.geo['horz']['y'][1]) z1 = 0.0 c1 = float(obj.geo['horz']['chords'][1]) x2 = float(obj.geo['horz']['x'][2]) y2 = float(obj.geo['horz']['y'][2]) z2 = 0.0 c2 = float(obj.geo['horz']['chords'][2]) # Profiles... Af0 = airconics.primitives.Airfoil([x0, y0, z0], ChordLength=c0, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af0.Curve, update=True, color='GREEN') Af1 = airconics.primitives.Airfoil([x1, y1, z1], ChordLength=c1, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af1.Curve, update=True, color='GREEN') Af2 = airconics.primitives.Airfoil([x2, y2, z2], ChordLength=c2, Rotation=0, Twist=0, Naca4Profile='0012') display.DisplayShape(Af2.Curve, update=True, color='GREEN') surf_HT = act.AddSurfaceLoft([Af0, Af1, Af2]) #------------- VT -------------------- # Add NACA 4 digit airfoils to loft between: # x0 = float(obj.geo['vert']['x'][0]) # y0 = 0.0 # z0 = float(obj.geo['vert']['z'][0]) x0 = float(obj.geo['vert']['x'][0]) y0 = 0.0 z0 = 1.0 c0 = float(obj.geo['vert']['chords'][0]) # z0 = obj.geo['Kink_wing']['zu'][0] #x1 = float(obj.geo['vert']['x'][1]) #y1 = 0.0 # z1 = float(obj.geo['vert']['z'][0]) x1 = float(obj.geo['vert']['x'][1]) y0 = 0.0 z1 = 5.5 c1 = float(obj.geo['vert']['chords'][1]) # Profiles... Af0 = airconics.primitives.Airfoil([x0, y0, z0], ChordLength=c0, Rotation=90, Twist=0, Naca4Profile='0012') display.DisplayShape(Af0.Curve, update=True, color='GREEN') Af1 = airconics.primitives.Airfoil([x1, y1, z1], ChordLength=c1, Rotation=90, Twist=0, Naca4Profile='0012') display.DisplayShape(Af1.Curve, update=True, color='GREEN') surf_VT = act.AddSurfaceLoft([Af0, Af1]) #------------- FUSELAGE -------------------- ## # fus = fuselage_oml.Fuselage(NoseLengthRatio=0.182, # TailLengthRatio=0.293, # Scaling=[55.902, 55.902, 55.902], # NoseCoordinates=[0.0, 0.0, 0], # CylindricalMidSection=False, # SimplificationReqd=False, # Maxi_attempt=5, # construct_geometry=True) # Current Display of the WHTVT display.DisplayShape(surf_wingin, update=True) display.DisplayShape(surf_wingout, update=True) display.DisplayShape(surf_HT, update=True) display.DisplayShape(surf_VT, update=True) #display.DisplayShape(fus, update=True) # fus.Display() start_display()
def transonic_airliner(display=None, Propulsion=1, EngineDia=2.9, FuselageScaling=[55.902, 55.902, 55.902], NoseLengthRatio=0.182, TailLengthRatio=0.293, WingScaleFactor=44.56, WingChordFactor=1.0, Topology=1, SpanStation1=0.35, SpanStation2=0.675, EngineCtrBelowLE=0.3558, EngineCtrFwdOfLE=0.9837, Scarf_deg=3): """ Parameters ---------- Propulsion - int 1 - twin 2 - quad EngineDia - float Diameter of engine intake highlight FuselageScaling - list, length 3 Fx, Fy, Fz scaling factors of fuselage NoseLengthRatio - scalar Proportion of forward tapering section of the fuselage TailLengthRatio - scalar Proportion of aft tapering section of the fuselage WingScaleFactor - scalar Scale Factor of the main wing WingChordFactor - scalar Chord factor of the main wing Topology - int Topology = 2 should yield a box wing airliner - use with caution SpanStation - float Inboard engine at this span station SpanStation2 - float Outboard engine at this span station (ignored if Propulsion=1) EngineCtrBelowLE - float Engine below leading edge, normalised by the length of the nacelle - range: [0.35,0.5] EngineCtrFwdOfLE - float Engine forward of leading edge, normalised by the length of the nacelle range: [0.85,1.5] Scarf_deg - scalar # Engine scarf angle Returns ------- airliner - 'Aircraft' class instance The collection of aircraft parts See also -------- class Aircraft """ try: Fus = fuselage_oml.Fuselage(NoseLengthRatio, TailLengthRatio, Scaling=FuselageScaling, NoseCoordinates=[0, 0, 0]) except: print "Fuselage fitting failed - stopping." return None FuselageHeight = FuselageScaling[2] * 0.105 FuselageLength = FuselageScaling[0] FuselageWidth = FuselageScaling[1] * 0.106 if Fus['OML'] is None: print "Failed to fit fuselage surface, stopping." return None # FSurf = rs.CopyObject(FuselageOMLSurf) # Position of the apex of the wing if FuselageHeight < 8.0: #787:[9.77,0,-0.307] WingApex = [0.1748 * FuselageLength, 0, -0.0523 * FuselageHeight] else: WingApex = [0.1748 * FuselageLength, 0, -0.1 * FuselageHeight] #787:[9.77,0,-0.307] # Set up the wing object, including the list of user-defined functions that # describe the spanwise variations of sweep, dihedral, etc. if Topology == 1: NSeg = 10 Wing = liftingsurface.LiftingSurface(WingApex, mySweepAngleFunctionAirliner, myDihedralFunctionAirliner, myTwistFunctionAirliner, myChordFunctionAirliner, myAirfoilFunctionAirliner, SegmentNo=NSeg, ScaleFactor=WingScaleFactor, ChordFactor=WingChordFactor) RootChord = Wing.RootChord elif Topology == 2: NSeg = 101 Wing = liftingsurface.LiftingSurface(WingApex, mySweepAngleFunctionAirliner, bw.myDihedralFunctionBoxWing, myTwistFunctionAirliner, myChordFunctionAirliner, myAirfoilFunctionAirliner, SegmentNo=NSeg, ScaleFactor=WingScaleFactor, ChordFactor=WingChordFactor) RootChord = Wing.RootChord if Topology == 1: # Add wing to body fairing WTBFXCentre = WingApex[ 0] + RootChord / 2.0 + RootChord * 0.1297 # 787: 23.8 if FuselageHeight < 8.0: #Note: I made changes to this in OCC Airconics to get a better fit # - Paul WTBFZ = RootChord * 0.009 #787: 0.2 WTBFheight = 1.8 * 0.1212 * RootChord #787:2.7 WTBFwidth = 1.08 * FuselageWidth else: WTBFZ = WingApex[2] + 0.005 * RootChord WTBFheight = 0.09 * RootChord WTBFwidth = 1.15 * FuselageWidth WTBFlength = 1.167 * RootChord #787:26 WBF_shape = act.make_ellipsoid([WTBFXCentre, 0, WTBFZ], WTBFlength, WTBFwidth, WTBFheight) WBF = AirconicsShape(components={'WBF': WBF_shape}) # Trim wing inboard section CutCirc = act.make_circle3pt([0, WTBFwidth / 4., -45], [0, WTBFwidth / 4., 45], [90, WTBFwidth / 4., 0]) CutCircDisk = act.PlanarSurf(CutCirc) Wing['Surface'] = act.TrimShapebyPlane(Wing['Surface'], CutCircDisk) elif Topology == 2: # Overlapping wing tips CutCirc = act.make_circle3pt((0, 0, -45), (0, 0, 45), (90, 0, 0)) CutCircDisk = act.PlanarSurf(CutCirc) Wing['Surface'] = act.TrimShapebyPlane(Wing['Surface'], CutCircDisk) # Engine installation (nacelle and pylon) NacelleLength = 1.95 * EngineDia if Propulsion == 1: SpanStations = [SpanStation1] elif Propulsion == 2: SpanStations = [SpanStation1, SpanStation2] engines = [] for i, SpanStation in enumerate(SpanStations): EngineSection, Chord = act.CutSect(Wing['Surface'], SpanStation) CEP = Chord.EndPoint() Centreloc = [ CEP.X() - EngineCtrFwdOfLE * NacelleLength, CEP.Y(), CEP.Z() - EngineCtrBelowLE * NacelleLength ] eng = engine.Engine(Chord, CentreLocation=Centreloc, ScarfAngle=Scarf_deg, HighlightRadius=EngineDia / 2.0, MeanNacelleLength=NacelleLength) engines.append(eng) # # Script for generating and positioning the fin # # Position of the apex of the fin P = [0.6524 * FuselageLength, 0.003, FuselageHeight * 0.384] #P = [36.47,0.003,2.254]55.902 if Topology == 1: ScaleFactor = WingScaleFactor / 2.032 #787:21.93 elif Topology == 2: ScaleFactor = WingScaleFactor / 3.5 SegmentNo = 100 ChordFactor = 1.01 #787:1.01 Fin = liftingsurface.LiftingSurface(P, mySweepAngleFunctionFin, myDihedralFunctionFin, myTwistFunctionFin, myChordFunctionFin, myAirfoilFunctionFin, SegmentNo=SegmentNo, ChordFactor=ChordFactor, ScaleFactor=ScaleFactor) # Create the rotation axis centered at the apex point in the x direction RotAxis = gp_Ax1(gp_Pnt(*P), gp_Dir(1, 0, 0)) Fin.RotateComponents(RotAxis, 90) if Topology == 1: # Tailplane P = [0.7692 * FuselageLength, 0.000, FuselageHeight * 0.29] SegmentNo = 100 ChordFactor = 1.01 ScaleFactor = 0.388 * WingScaleFactor #787:17.3 TP = liftingsurface.LiftingSurface(P, mySweepAngleFunctionTP, myDihedralFunctionTP, myTwistFunctionTP, myChordFunctionTP, myAirfoilFunctionTP, SegmentNo=SegmentNo, ChordFactor=ChordFactor, ScaleFactor=ScaleFactor) # OCC_AirCONICS Note: Nothing below here implemented in OCC_AirCONICS - See # Rhino version for this functionality (largely for display only) # # rs.DeleteObjects([EngineSection, Chord]) # try: # rs.DeleteObjects([CutCirc]) # except: # pass # # try: # rs.DeleteObjects([CutCircDisk]) # except: # pass # # # Windows # # # Cockpit windows: CockpitWindowTop = 0.305 * FuselageHeight print("Making Fuselage Windows...") # solids = Fus.CockpitWindowContours(Height=CockpitWindowTop, Depth=6) # ## Cut the windows out: # for solid in solids: # Fus['OML'] = act.SplitShape(Fus['OML'], solid) # # # print("Cockpit Windows Done.") ## ## (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax) = act.ObjectsExtents([Win1, Win2, Win3, Win4]) CockpitBulkheadX = NoseLengthRatio * FuselageLength * 0.9 ## ## CockpitWallPlane = rs.PlaneFromPoints([CockpitBulkheadX, -15,-15], ## [CockpitBulkheadX,15,-15], ## [CockpitBulkheadX,-15,15]) ## ## CockpitWall = rs.AddPlaneSurface(CockpitWallPlane, 30, 30) ## ## if 'WTBF' in locals(): ## rs.TrimBrep(WTBF, CockpitWall) ## ## rs.DeleteObject(CockpitWall) # ## # Window lines WIN = [1] NOWIN = [0] ## ### # A typical window pattern (including emergency exit windows) WinVec = WIN + 2 * NOWIN + 9 * WIN + 3 * NOWIN + WIN + NOWIN + 24 * WIN + 2 * NOWIN + WIN + NOWIN + 14 * WIN + 2 * NOWIN + WIN + 20 * WIN + 2 * NOWIN + WIN + NOWIN + 20 * WIN wires = [] if FuselageHeight < 8.0: ### # Single deck WindowLineHeight = 0.3555 * FuselageHeight WinX = 0.1157 * FuselageLength WindowPitch = 0.609 WinInd = -1 i = 0 while WinX < 0.75 * FuselageLength: WinInd = WinInd + 1 if WinVec[WinInd] == 1 and WinX > CockpitBulkheadX: i = i + 1 print("Generating cabin window {}".format(i)) WinCenter = [WinX, WindowLineHeight] W_wire = Fus.WindowContour(WinCenter) wires.append(W_wire) # display.DisplayShape(W_wire, color='black') # win_port, win_stbd = Fus.MakeWindow(*WinCenter) # print(type(win_port), type(win_stbd)) # # display.DisplayShape(win_port, color='Black') # display.DisplayShape(win_stbd, color='Black') # ### Note: Need to fix makewindow to return windows WinStbd, ## # WinPort, # Fus.MakeWindow(WinX, WindowLineHeight) ### act.AssignMaterial(WinStbd,"Plexiglass") ### act.AssignMaterial(WinPort,"Plexiglass") WinX = WinX + WindowPitch # # print("Cabin windows done") # else: # # TODO: Fuselage big enough to accommodate two decks # # Lower deck # WindowLineHeight = 0.17*FuselageHeight #0.166 # WinX = 0.1*FuselageLength #0.112 # WindowPitch = 0.609 # WinInd = 0 # while WinX < 0.757*FuselageLength: # WinInd = WinInd + 1 # if WinVec[WinInd] == 1 and WinX > CockpitBulkheadX: # WinStbd, WinPort, FuselageOMLSurf = fuselage_oml.MakeWindow(FuselageOMLSurf, WinX, WindowLineHeight) # act.AssignMaterial(WinStbd,"Plexiglass") # act.AssignMaterial(WinPort,"Plexiglass") # WinX = WinX + WindowPitch # # Upper deck # WindowLineHeight = 0.49*FuselageHeight # WinX = 0.174*FuselageLength #0.184 # WinInd = 0 # while WinX < 0.757*FuselageLength: # WinInd = WinInd + 1 # if WinVec[WinInd] == 1 and WinX > CockpitBulkheadX: # WinStbd, WinPort, FuselageOMLSurf = fuselage_oml.MakeWindow(FuselageOMLSurf, WinX, WindowLineHeight) # act.AssignMaterial(WinStbd,"Plexiglass") # act.AssignMaterial(WinPort,"Plexiglass") # WinX = WinX + WindowPitch # # # # # # act.AssignMaterial(FuselageOMLSurf,"White_composite_external") # act.AssignMaterial(WingSurf,"White_composite_external") # try: # act.AssignMaterial(TPSurf,"ShinyBARedMetal") # except: # pass # act.AssignMaterial(FinSurf,"ShinyBARedMetal") # act.AssignMaterial(Win1,"Plexiglass") # act.AssignMaterial(Win2,"Plexiglass") # act.AssignMaterial(Win3,"Plexiglass") # act.AssignMaterial(Win4,"Plexiglass") # # # # Mirror the geometry as required Wing2 = Wing.MirrorComponents(plane='xz') try: # this try section allows box wing i.e. no tailplane TP2 = TP.MirrorComponents(plane='xz') except: pass engines_left = [] for eng in engines: engines_left.append(eng.MirrorComponents(plane='xz')) # if Propulsion == 1: # for ObjId in EngineStbd: # act.MirrorObjectXZ(ObjId) # act.MirrorObjectXZ(PylonStbd) # elif Propulsion == 2: # raise NotImplementedError # for ObjId in EngineStbd1: # act.MirrorObjectXZ(ObjId) # act.MirrorObjectXZ(PylonStbd1) # for ObjId in EngineStbd2: # act.MirrorObjectXZ(ObjId) # act.MirrorObjectXZ(PylonStbd2) # Build the return assembly (could change this later based on input 'tree': airliner = AirconicsCollection( parts={ 'Wing_right': Wing, 'Wing_left': Wing2, 'Fuselage': Fus, 'Fin': Fin, 'Tailplane_right': TP, 'Tailplane_left': TP2, 'WBF': WBF }) # Loop over the engines and write all components: for i, eng in enumerate(engines): name = 'engine_right' + str(i + 1) airliner.AddPart(eng, name) for i, eng in enumerate(engines_left): name = 'engine_left' + str(i + 1) airliner.AddPart(eng, name) return airliner, wires
ScaleFactor = 44.56 Wing = LiftingSurface(P, wingex.mySweepAngleFunctionAirliner, wingex.myDihedralFunctionAirliner, wingex.myTwistFunctionAirliner, wingex.myChordFunctionAirliner, wingex.myAirfoilFunctionAirliner, SegmentNo=SegmentNo, ChordFactor=ChordFactor, ScaleFactor=ScaleFactor) Wing.Display(display) SpanStation = 0.3 # The engine is to be placed at 30% span EngineDia = 2.9 NacelleLength = 1.95*EngineDia EngineSection, HChord = act.CutSect(Wing['Surface'], SpanStation) Chord = HChord.GetObject() CEP = Chord.EndPoint() display.DisplayShape(Chord, update=True, color='black') # Variables controlling the position of the engine with respect to the wing EngineCtrFwdOfLE = 0.98 EngineCtrBelowLE = 0.35 Scarf_deg = 4 Centreloc = [CEP.X()-EngineCtrFwdOfLE*NacelleLength, CEP.Y(), CEP.Z()-EngineCtrBelowLE*NacelleLength] # Now build the engine and its pylon eng1 = Engine(HChord, CentreLocation=Centreloc, ScarfAngle=Scarf_deg,
def _BuildPanels(self, ChordFactor, ScaleFactor): LESpar, TESpar, MIDSpar, StringerUp, StringerDown, PointsUp, PointsDown = self._BuildSpars( self.ChordFactor, self.ScaleFactor) PanelUp = [] PanelDown = [] cont = 1 for ii in range(0, len(PointsUp) - self.NoStiffners - 1): if cont == self.NoStiffners: cont = 0 else: cont = cont # Panel from segments SegH1 = GC_MakeSegment( PointsUp[ii], PointsUp[ii + self.NoStiffners]).Value() SegH2 = GC_MakeSegment(PointsUp[ii + 1], PointsUp[ii + self.NoStiffners + 1]).Value() SegV1 = GC_MakeSegment(PointsUp[ii], PointsUp[ii + 1]).Value() SegV2 = GC_MakeSegment(PointsUp[ii + self.NoStiffners], PointsUp[ii + self.NoStiffners + 1]).Value() EdgeHUp1 = act.make_edge(SegH1) EdgeHUp2 = act.make_edge(SegH2) EdgeVUp1 = act.make_edge(SegV1) EdgeVUp2 = act.make_edge(SegV2) WirePanelUp = act.make_wire( [EdgeHUp1, EdgeVUp1, EdgeHUp2, EdgeVUp2]) PanelUpi = act.make_face(WirePanelUp) # In this way the pannel will be ordered in alternance between upper and lower surface SegH1 = GC_MakeSegment( PointsDown[ii], PointsDown[ii + self.NoStiffners]).Value() SegH2 = GC_MakeSegment(PointsDown[ii + 1], PointsDown[ii + self.NoStiffners + 1]).Value() SegV1 = GC_MakeSegment(PointsDown[ii], PointsDown[ii + 1]).Value() SegV2 = GC_MakeSegment(PointsDown[ii + self.NoStiffners], PointsDown[ii + self.NoStiffners + 1]).Value() EdgeHUp1 = act.make_edge(SegH1) EdgeHUp2 = act.make_edge(SegH2) EdgeVUp1 = act.make_edge(SegV1) EdgeVUp2 = act.make_edge(SegV2) WirePanelDown = act.make_wire( [EdgeHUp1, EdgeVUp1, EdgeHUp2, EdgeVUp2]) PanelDowni = act.make_face(WirePanelDown) if self.ScaleFactor != 1: Origin = gp_Pnt(0., 0., 0.) PanelUpi = act.scale_uniformal(PanelUpi, Origin, self.ScaleFactor) PanelDowni = act.scale_uniformal(PanelDowni, Origin, self.ScaleFactor) PanelUp.append(PanelUpi) PanelDown.append(PanelDowni) cont = cont + 1 return PanelUp, PanelDown
def _BuildRibs(self, ChordFactor, ScaleFactor): """Generates Ribs surface along the wingspan, given the general, nondimensional parameters of the object (variations of chord length, dihedral, etc.) and the two scaling factors. Parameters ---------- ChordFactor - float Factor againt which the standard shape is scaled in the chordwise direction ScaleFactor - float Factor againt which the standard shape is scaled in the world coordinates Returns ------- Ribs : TopoDS_Shape The generated Ribs surface """ SectionsRibs = [] RibsFace = [] Step = (self.SegmentNoLoft) / (self.NoRibs - 1) LEPointsR = self._GenerateLeadingEdge() Eps = np.linspace(0, 1, self.SegmentNoLoft + 1) SectionsRibs = [ self.AirfoilFunct(Eps[i], LEPointsR[i], self.ChordFunct, ChordFactor, self.DihedralFunct, self.TwistFunct).Curve for i in xrange(0, self.SegmentNoLoft + 1, Step) ] LESpar, TESpar, MIDSpar, StringerUp, StringerDown, PointsUp, PointsDown = self._BuildSpars( self.ChordFactor, self.ScaleFactor) # RIBS generated from segments for i in range(0, self.NoRibs): for ii in range(0, self.NoStiffners - 1): SegUp = GC_MakeSegment( PointsUp[ii + i * self.NoStiffners * (Step)], PointsUp[ii + i * self.NoStiffners * (Step) + 1]).Value() SegDown = GC_MakeSegment( PointsDown[ii + i * self.NoStiffners * (Step) + 1], PointsDown[ii + i * self.NoStiffners * (Step)]).Value() SegSide1 = GC_MakeSegment( PointsDown[ii + i * self.NoStiffners * (Step)], PointsUp[ii + i * self.NoStiffners * (Step)]).Value() SegSide2 = GC_MakeSegment( PointsUp[ii + i * self.NoStiffners * (Step) + 1], PointsDown[ii + i * self.NoStiffners * (Step) + 1]).Value() EdgeSegUp = act.make_edge(SegUp) EdgeSegDown = act.make_edge(SegDown) EdgeSide1 = act.make_edge(SegSide1) EdgeSide2 = act.make_edge(SegSide2) WireRib = act.make_wire( [EdgeSide1, EdgeSegUp, EdgeSide2, EdgeSegDown]) FaceRibi = act.make_face(WireRib) if self.ScaleFactor != 1: Origin = gp_Pnt(0., 0., 0.) FaceRib = act.scale_uniformal(FaceRibi, Origin, self.ScaleFactor) RibsFace.append(FaceRib) return SectionsRibs, RibsFace
def _BuildSpars(self, ChordFactor, ScaleFactor): LE = self._GenerateLeadingEdge() self.NoStiffners = self.NoStiffnersLE + self.NoStiffnersTE SectionsProfiles = [] SparLEFullWing = [] SparTEFullWing = [] SparMIDFullWing = [] SparLEup = [] SparLEdown = [] SparMIDup = [] SparMIDdown = [] SparTEup = [] SparTEdown = [] planeStiffEps = [] PStiffUpFullWing = [] PStiffDownFullWing = [] StringerUpFullWing = [] StringerDownFullWing = [] EpsS = np.linspace(0, 1, self.SegmentNoLoft + 1) SectionsProfiles = [ self.AirfoilFunct(EpsS[d], LE[d], self.ChordFunct, ChordFactor, self.DihedralFunct, self.TwistFunct).Curve for d in xrange(self.SegmentNoLoft + 1) ] # Stringers generation h = 0 cont3 = 0 PointsUp = [] PointsDown = [] PointsMIDup = [] PointsMIDdown = [] for SecR in SectionsProfiles: ChordLenght = ((ChordFactor * self.ChordFunct(EpsS[h])) / np.cos(np.radians(self.TwistFunct(EpsS[h])))) LELengthX = LE[h, 0] LEplanePositionX = (self.PositionLESpar * ChordLenght) * np.cos( self.TwistFunct(EpsS[h])) + LELengthX TEplanePositionX = (self.PositionTESpar * ChordLenght) * np.cos( self.TwistFunct(EpsS[h])) + LELengthX MIDplanePositionX = (self.PositionMIDSpar * ChordLenght) * np.cos( self.TwistFunct(EpsS[h])) + LELengthX planeLEi = Geom_Plane( gp_Pln(gp_Pnt(LEplanePositionX, 0., 0.), gp_Dir(gp_Vec(gp_Pnt(0., 0., 0.), gp_Pnt(1., 0., 0.))))) planeMIDi = Geom_Plane( gp_Pln(gp_Pnt(MIDplanePositionX, 0., 0.), gp_Dir(gp_Vec(gp_Pnt(0., 0., 0.), gp_Pnt(1., 0., 0.))))) planeTEi = Geom_Plane( gp_Pln(gp_Pnt(TEplanePositionX, 0., 0.), gp_Dir(gp_Vec(gp_Pnt(0., 0., 0.), gp_Pnt(1., 0., 0.))))) # planeLEi.Rotate(gp_OY(), -np.radians(self.TwistFunct(EpsS[h]))) # planeMIDi.Rotate(gp_OY(), -np.radians(self.TwistFunct(EpsS[h]))) # planeTEi.Rotate(gp_OY(), -np.radians(self.TwistFunct(EpsS[h]))) SegmentStiffLE = (MIDplanePositionX - LEplanePositionX) / (self.NoStiffnersLE - 1) SegmentStiffTE = (TEplanePositionX - MIDplanePositionX) / (self.NoStiffnersTE) NoStiffners = self.NoStiffnersLE + self.NoStiffnersTE PStiffUpi = [] PStiffDowni = [] PosStiffiEps = LEplanePositionX for g in xrange(NoStiffners): planeStiffEps = Geom_Plane( gp_Pln( gp_Pnt(PosStiffiEps, 0., 0.), gp_Dir(gp_Vec(gp_Pnt(0., 0., 0.), gp_Pnt(1., 0., 0.))))) StiffiEps = GeomAPI_IntCS(SecR, planeStiffEps.GetHandle()) with act.assert_isdone(StiffiEps, 'failed to calculate intersection'): nb_results = StiffiEps.NbPoints() if nb_results == 1: return StiffiEps.Point(1) #print("One point intersection") elif nb_results >= 1: #print("More than one intersection point") PStiff = [] for i in range(1, nb_results + 1): PStiff.append(StiffiEps.Point(i)) else: return None PStiffUpi.append(PStiff[0]) PStiffDowni.append(PStiff[nb_results - 1]) if g <= self.NoStiffnersLE - 2: PosStiffiEps = PosStiffiEps + SegmentStiffLE else: PosStiffiEps = PosStiffiEps + SegmentStiffTE PointsUp.append(PStiff[0]) PointsDown.append(PStiff[nb_results - 1]) SparLEi = GeomAPI_IntCS(SecR, planeLEi.GetHandle()) with act.assert_isdone(SparLEi, 'failed to calculate intersection'): nb_results = SparLEi.NbPoints() #print(nb_results) if nb_results == 1: return SparLEi.Point(1) #print("One point intersection") elif nb_results >= 1: #print("More than one intersection point") PLE = [] for i in range(1, nb_results + 1): PLE.append(SparLEi.Point(i)) else: return None SegLE = GC_MakeSegment(PLE[0], PLE[nb_results - 1]).Value() SparMIDi = GeomAPI_IntCS(SecR, planeMIDi.GetHandle()) with act.assert_isdone(SparMIDi, 'failed to calculate intersection'): nb_results = SparMIDi.NbPoints() #print(nb_results) if nb_results == 1: return SparMIDi.Point(1) #print("One point intersection") elif nb_results >= 1: #print("More than one intersection point") PMID = [] for i in range(1, nb_results + 1): PMID.append(SparMIDi.Point(i)) else: return None SegMID = GC_MakeSegment(PMID[0], PMID[nb_results - 1]).Value() PointsMIDup.append(PMID[0]) PointsMIDdown.append(PMID[nb_results - 1]) SparTEi = GeomAPI_IntCS(SecR, planeTEi.GetHandle()) with act.assert_isdone(SparTEi, 'failed to calculate intersection'): nb_results = SparTEi.NbPoints() #print(nb_results) if nb_results == 1: return SparTEi.Point(1) #print("One point intersection") elif nb_results >= 1: #print("More than one intersection point") PTE = [] for i in range(1, nb_results + 1): PTE.append(SparTEi.Point(i)) else: return None SegTE = GC_MakeSegment(PTE[0], PTE[nb_results - 1]).Value() #print(len(SparMIDdown)) #print(len(SparMIDup)) #print(len(SparLEup)) #print(len(SparLEdown)) SparLEFullWing.append(SegLE) SparMIDFullWing.append(SegMID) SparTEFullWing.append(SegTE) SparLEup.append(PLE[0]) SparLEdown.append(PLE[nb_results - 1]) SparMIDup.append(PMID[0]) #print(PMID[nb_results-1]) SparMIDdown.append(PMID[nb_results - 1]) SparTEup.append(PTE[0]) SparTEdown.append(PTE[nb_results - 1]) PStiffUpFullWing.append(PStiffUpi) PStiffDownFullWing.append(PStiffDowni) cont3 = cont3 + 1 h = h + 1 # Method to create spars - VIA SEGMENTS #LE LoftLESparFullWing = [] for iii in xrange(0, len(PointsUp) - 2 * (self.NoStiffners - 1), self.NoStiffners): SegUp = GC_MakeSegment(PointsUp[iii], PointsUp[iii + self.NoStiffners]).Value() SegDown = GC_MakeSegment(PointsDown[iii + self.NoStiffners], PointsDown[iii]).Value() SegSide1 = GC_MakeSegment(PointsDown[iii], PointsUp[iii]).Value() SegSide2 = GC_MakeSegment(PointsUp[iii + self.NoStiffners], PointsDown[iii + self.NoStiffners]).Value() EdgeSegUp = act.make_edge(SegUp) EdgeSegDown = act.make_edge(SegDown) EdgeSide1 = act.make_edge(SegSide1) EdgeSide2 = act.make_edge(SegSide2) WireSparLE = act.make_wire( [EdgeSide1, EdgeSegUp, EdgeSide2, EdgeSegDown]) FaceSparLEi = act.make_face(WireSparLE) if self.ScaleFactor != 1: Origin = gp_Pnt(0., 0., 0.) FaceSparLE = act.scale_uniformal(FaceSparLEi, Origin, self.ScaleFactor) LoftLESparFullWing.append(FaceSparLE) #MID LoftMIDSparFullWing = [] for iii in xrange(0, self.SegmentNoLoft): SegUp = GC_MakeSegment(PointsMIDup[iii], PointsMIDup[iii + 1]).Value() SegDown = GC_MakeSegment(PointsMIDdown[iii + 1], PointsMIDdown[iii]).Value() SegSide1 = GC_MakeSegment(PointsMIDdown[iii], PointsMIDup[iii]).Value() SegSide2 = GC_MakeSegment(PointsMIDup[iii + 1], PointsMIDdown[iii + 1]).Value() EdgeSegUp = act.make_edge(SegUp) EdgeSegDown = act.make_edge(SegDown) EdgeSide1 = act.make_edge(SegSide1) EdgeSide2 = act.make_edge(SegSide2) WireSparMID = act.make_wire( [EdgeSide1, EdgeSegUp, EdgeSide2, EdgeSegDown]) FaceSparMIDi = act.make_face(WireSparMID) if self.ScaleFactor != 1: Origin = gp_Pnt(0., 0., 0.) FaceSparMID = act.scale_uniformal(FaceSparMIDi, Origin, self.ScaleFactor) LoftMIDSparFullWing.append(FaceSparMID) #TE LoftTESparFullWing = [] for iii in xrange(self.NoStiffners - 1, len(PointsUp) - (self.NoStiffners), self.NoStiffners): SegUp = GC_MakeSegment(PointsUp[iii], PointsUp[iii + self.NoStiffners]).Value() SegDown = GC_MakeSegment(PointsDown[iii + self.NoStiffners], PointsDown[iii]).Value() SegSide1 = GC_MakeSegment(PointsDown[iii], PointsUp[iii]).Value() SegSide2 = GC_MakeSegment(PointsUp[iii + self.NoStiffners], PointsDown[iii + self.NoStiffners]).Value() EdgeSegUp = act.make_edge(SegUp) EdgeSegDown = act.make_edge(SegDown) EdgeSide1 = act.make_edge(SegSide1) EdgeSide2 = act.make_edge(SegSide2) WireSparTE = act.make_wire( [EdgeSide1, EdgeSegUp, EdgeSide2, EdgeSegDown]) FaceSparTEi = act.make_face(WireSparTE) if self.ScaleFactor != 1: Origin = gp_Pnt(0., 0., 0.) FaceSparTE = act.scale_uniformal(FaceSparTEi, Origin, self.ScaleFactor) LoftTESparFullWing.append(FaceSparTE) for g in range(self.NoStiffners): for gg in range(self.SegmentNoLoft): SegStringerUp = GC_MakeSegment( PointsUp[gg * self.NoStiffners + g], PointsUp[gg * self.NoStiffners + g + self.NoStiffners]).Value() SegStringerDown = GC_MakeSegment( PointsDown[gg * self.NoStiffners + g], PointsDown[gg * self.NoStiffners + g + self.NoStiffners]).Value() EdgeUp = act.make_edge(SegStringerUp) EdgeDown = act.make_edge(SegStringerDown) WireStringUp = act.make_wire(EdgeUp) WireStringDown = act.make_wire(EdgeDown) if self.ScaleFactor != 1: Origin = gp_Pnt(0., 0., 0.) StrUpFullWingi = act.scale_uniformal( WireStringUp, Origin, self.ScaleFactor) StrDownFullWingi = act.scale_uniformal( WireStringDown, Origin, self.ScaleFactor) #print('hello') #print(self.ScaleFactor) StringerUpFullWing.append(StrUpFullWingi) StringerDownFullWing.append(StrDownFullWingi) return LoftLESparFullWing, LoftTESparFullWing, LoftMIDSparFullWing, StringerUpFullWing, StringerDownFullWing, PointsUp, PointsDown
""" if __name__ == "__main__": import airconics import airconics.AirCONICStools as act # Initialise the display from OCC.Display.SimpleGui import init_display display, start_display, add_menu, add_function_to_menu = init_display() # Add NACA 4 digit airfoils to loft between: Af2 = airconics.primitives.Airfoil([0., 0., 0.], ChordLength=3., Naca4Profile='2412') display.DisplayShape(Af2.Curve, update=True, color='GREEN') Af3 = airconics.primitives.Airfoil([0., 5., 0.], ChordLength=1., Naca4Profile='0012') display.DisplayShape(Af3.Curve, update=True, color='GREEN') Af4 = airconics.primitives.Airfoil([0., 6., 0.2], ChordLength=0.2, Naca4Profile='0012') display.DisplayShape(Af4.Curve, update=True, color='GREEN') surf = act.AddSurfaceLoft([Af2, Af3, Af4]) # Note that surf is a TOPO_DS Shape, and hence no surf.Shape is required for display display.DisplayShape(surf, update=True) start_display()
def transonic_airliner(display=None, Propulsion=1, EngineDia=2.9, FuselageScaling=[55.902, 55.902, 55.902], NoseLengthRatio=0.182, TailLengthRatio=0.293, WingScaleFactor=44.56, WingChordFactor=1.0, Topology=1, SpanStation1=0.35, SpanStation2=0.675, EngineCtrBelowLE=0.3558, EngineCtrFwdOfLE=0.9837, Scarf_deg=3): """ Parameters ---------- Propulsion - int 1 - twin 2 - quad EngineDia - float Diameter of engine intake highlight FuselageScaling - list, length 3 Fx, Fy, Fz scaling factors of fuselage NoseLengthRatio - scalar Proportion of forward tapering section of the fuselage TailLengthRatio - scalar Proportion of aft tapering section of the fuselage WingScaleFactor - scalar Scale Factor of the main wing WingChordFactor - scalar Chord factor of the main wing Topology - int Topology = 2 should yield a box wing airliner - use with caution SpanStation - float Inboard engine at this span station SpanStation2 - float Outboard engine at this span station (ignored if Propulsion=1) EngineCtrBelowLE - float Engine below leading edge, normalised by the length of the nacelle - range: [0.35,0.5] EngineCtrFwdOfLE - float Engine forward of leading edge, normalised by the length of the nacelle range: [0.85,1.5] Scarf_deg - scalar # Engine scarf angle Returns ------- airliner - 'Aircraft' class instance The collection of aircraft parts See also -------- class Aircraft """ try: Fus = fuselage_oml.Fuselage(NoseLengthRatio, TailLengthRatio, Scaling=FuselageScaling, NoseCoordinates=[0, 0, 0]) except: print "Fuselage fitting failed - stopping." return None FuselageHeight = FuselageScaling[2]*0.105 FuselageLength = FuselageScaling[0] FuselageWidth = FuselageScaling[1]*0.106 if Fus['OML'] is None: print "Failed to fit fuselage surface, stopping." return None # FSurf = rs.CopyObject(FuselageOMLSurf) # Position of the apex of the wing if FuselageHeight < 8.0: #787:[9.77,0,-0.307] WingApex = [0.1748*FuselageLength,0,-0.0523*FuselageHeight] else: WingApex = [0.1748*FuselageLength,0,-0.1*FuselageHeight] #787:[9.77,0,-0.307] # Set up the wing object, including the list of user-defined functions that # describe the spanwise variations of sweep, dihedral, etc. if Topology == 1: NSeg = 10 Wing = liftingsurface.LiftingSurface(WingApex, mySweepAngleFunctionAirliner, myDihedralFunctionAirliner, myTwistFunctionAirliner, myChordFunctionAirliner, myAirfoilFunctionAirliner, SegmentNo=NSeg, ScaleFactor=WingScaleFactor, ChordFactor=WingChordFactor) RootChord = Wing.RootChord elif Topology == 2: NSeg = 101 Wing = liftingsurface.LiftingSurface(WingApex, mySweepAngleFunctionAirliner, bw.myDihedralFunctionBoxWing, myTwistFunctionAirliner, myChordFunctionAirliner, myAirfoilFunctionAirliner, SegmentNo=NSeg, ScaleFactor=WingScaleFactor, ChordFactor=WingChordFactor) RootChord = Wing.RootChord if Topology == 1: # Add wing to body fairing WTBFXCentre = WingApex[0] + RootChord/2.0 + RootChord*0.1297 # 787: 23.8 if FuselageHeight < 8.0: #Note: I made changes to this in OCC Airconics to get a better fit # - Paul WTBFZ = RootChord*0.009 #787: 0.2 WTBFheight = 1.8*0.1212*RootChord #787:2.7 WTBFwidth = 1.08*FuselageWidth else: WTBFZ = WingApex[2] + 0.005*RootChord WTBFheight = 0.09*RootChord WTBFwidth = 1.15*FuselageWidth WTBFlength = 1.167*RootChord #787:26 WBF_shape = act.make_ellipsoid([WTBFXCentre, 0, WTBFZ], WTBFlength, WTBFwidth, WTBFheight) WBF = AirconicsShape(components={'WBF': WBF_shape}) # Trim wing inboard section CutCirc = act.make_circle3pt([0,WTBFwidth/4.,-45], [0,WTBFwidth/4.,45], [90,WTBFwidth/4.,0]) CutCircDisk = act.PlanarSurf(CutCirc) Wing['Surface'] = act.TrimShapebyPlane(Wing['Surface'], CutCircDisk) elif Topology == 2: # Overlapping wing tips CutCirc = act.make_circle3pt((0,0,-45), (0,0,45), (90,0,0)) CutCircDisk = act.PlanarSurf(CutCirc) Wing['Surface'] = act.TrimShapebyPlane(Wing['Surface'], CutCircDisk) # Engine installation (nacelle and pylon) NacelleLength = 1.95*EngineDia if Propulsion == 1: SpanStations = [SpanStation1] elif Propulsion == 2: SpanStations = [SpanStation1, SpanStation2] engines = [] for i, SpanStation in enumerate(SpanStations): EngineSection, Chord = act.CutSect(Wing['Surface'], SpanStation) CEP = Chord.EndPoint() Centreloc = [CEP.X()-EngineCtrFwdOfLE*NacelleLength, CEP.Y(), CEP.Z()-EngineCtrBelowLE*NacelleLength] eng = engine.Engine(Chord, CentreLocation=Centreloc, ScarfAngle=Scarf_deg, HighlightRadius=EngineDia/2.0, MeanNacelleLength = NacelleLength) engines.append(eng) # # Script for generating and positioning the fin # # Position of the apex of the fin P = [0.6524*FuselageLength,0.003,FuselageHeight*0.384] #P = [36.47,0.003,2.254]55.902 if Topology == 1: ScaleFactor = WingScaleFactor/2.032 #787:21.93 elif Topology == 2: ScaleFactor = WingScaleFactor/3.5 SegmentNo = 100 ChordFactor = 1.01#787:1.01 Fin = liftingsurface.LiftingSurface(P, mySweepAngleFunctionFin, myDihedralFunctionFin, myTwistFunctionFin, myChordFunctionFin, myAirfoilFunctionFin, SegmentNo=SegmentNo, ChordFactor=ChordFactor, ScaleFactor=ScaleFactor) # Create the rotation axis centered at the apex point in the x direction RotAxis = gp_Ax1(gp_Pnt(*P), gp_Dir(1, 0, 0)) Fin.RotateComponents(RotAxis, 90) if Topology == 1: # Tailplane P = [0.7692*FuselageLength,0.000,FuselageHeight*0.29] SegmentNo = 100 ChordFactor = 1.01 ScaleFactor = 0.388*WingScaleFactor #787:17.3 TP = liftingsurface.LiftingSurface(P, mySweepAngleFunctionTP, myDihedralFunctionTP, myTwistFunctionTP, myChordFunctionTP, myAirfoilFunctionTP, SegmentNo=SegmentNo, ChordFactor=ChordFactor, ScaleFactor=ScaleFactor) # OCC_AirCONICS Note: Nothing below here implemented in OCC_AirCONICS - See # Rhino version for this functionality (largely for display only) # # rs.DeleteObjects([EngineSection, Chord]) # try: # rs.DeleteObjects([CutCirc]) # except: # pass # # try: # rs.DeleteObjects([CutCircDisk]) # except: # pass # # # Windows # # # Cockpit windows: CockpitWindowTop = 0.305*FuselageHeight print("Making Fuselage Windows...") # solids = Fus.CockpitWindowContours(Height=CockpitWindowTop, Depth=6) # ## Cut the windows out: # for solid in solids: # Fus['OML'] = act.SplitShape(Fus['OML'], solid) # # # print("Cockpit Windows Done.") ## ## (Xmin,Ymin,Zmin,Xmax,Ymax,Zmax) = act.ObjectsExtents([Win1, Win2, Win3, Win4]) CockpitBulkheadX = NoseLengthRatio*FuselageLength*0.9 ## ## CockpitWallPlane = rs.PlaneFromPoints([CockpitBulkheadX, -15,-15], ## [CockpitBulkheadX,15,-15], ## [CockpitBulkheadX,-15,15]) ## ## CockpitWall = rs.AddPlaneSurface(CockpitWallPlane, 30, 30) ## ## if 'WTBF' in locals(): ## rs.TrimBrep(WTBF, CockpitWall) ## ## rs.DeleteObject(CockpitWall) # ## # Window lines WIN = [1] NOWIN = [0] ## ### # A typical window pattern (including emergency exit windows) WinVec = WIN + 2*NOWIN + 9*WIN + 3*NOWIN + WIN + NOWIN + 24*WIN + 2*NOWIN + WIN + NOWIN + 14*WIN + 2*NOWIN + WIN + 20*WIN + 2*NOWIN + WIN + NOWIN + 20*WIN wires = [] if FuselageHeight < 8.0: ### # Single deck WindowLineHeight = 0.3555*FuselageHeight WinX = 0.1157*FuselageLength WindowPitch = 0.609 WinInd = -1 i = 0 while WinX < 0.75*FuselageLength: WinInd = WinInd + 1 if WinVec[WinInd] == 1 and WinX > CockpitBulkheadX: i=i+1 print("Generating cabin window {}".format(i)) WinCenter = [WinX, WindowLineHeight] W_wire = Fus.WindowContour(WinCenter) wires.append(W_wire) # display.DisplayShape(W_wire, color='black') # win_port, win_stbd = Fus.MakeWindow(*WinCenter) # print(type(win_port), type(win_stbd)) # # display.DisplayShape(win_port, color='Black') # display.DisplayShape(win_stbd, color='Black') # ### Note: Need to fix makewindow to return windows WinStbd, ## # WinPort, # Fus.MakeWindow(WinX, WindowLineHeight) ### act.AssignMaterial(WinStbd,"Plexiglass") ### act.AssignMaterial(WinPort,"Plexiglass") WinX = WinX + WindowPitch # # print("Cabin windows done") # else: # # TODO: Fuselage big enough to accommodate two decks # # Lower deck # WindowLineHeight = 0.17*FuselageHeight #0.166 # WinX = 0.1*FuselageLength #0.112 # WindowPitch = 0.609 # WinInd = 0 # while WinX < 0.757*FuselageLength: # WinInd = WinInd + 1 # if WinVec[WinInd] == 1 and WinX > CockpitBulkheadX: # WinStbd, WinPort, FuselageOMLSurf = fuselage_oml.MakeWindow(FuselageOMLSurf, WinX, WindowLineHeight) # act.AssignMaterial(WinStbd,"Plexiglass") # act.AssignMaterial(WinPort,"Plexiglass") # WinX = WinX + WindowPitch # # Upper deck # WindowLineHeight = 0.49*FuselageHeight # WinX = 0.174*FuselageLength #0.184 # WinInd = 0 # while WinX < 0.757*FuselageLength: # WinInd = WinInd + 1 # if WinVec[WinInd] == 1 and WinX > CockpitBulkheadX: # WinStbd, WinPort, FuselageOMLSurf = fuselage_oml.MakeWindow(FuselageOMLSurf, WinX, WindowLineHeight) # act.AssignMaterial(WinStbd,"Plexiglass") # act.AssignMaterial(WinPort,"Plexiglass") # WinX = WinX + WindowPitch # # # # # # act.AssignMaterial(FuselageOMLSurf,"White_composite_external") # act.AssignMaterial(WingSurf,"White_composite_external") # try: # act.AssignMaterial(TPSurf,"ShinyBARedMetal") # except: # pass # act.AssignMaterial(FinSurf,"ShinyBARedMetal") # act.AssignMaterial(Win1,"Plexiglass") # act.AssignMaterial(Win2,"Plexiglass") # act.AssignMaterial(Win3,"Plexiglass") # act.AssignMaterial(Win4,"Plexiglass") # # # # Mirror the geometry as required Wing2 = Wing.MirrorComponents(plane='xz') try: # this try section allows box wing i.e. no tailplane TP2 = TP.MirrorComponents(plane='xz') except: pass engines_left = [] for eng in engines: engines_left.append(eng.MirrorComponents(plane='xz')) # if Propulsion == 1: # for ObjId in EngineStbd: # act.MirrorObjectXZ(ObjId) # act.MirrorObjectXZ(PylonStbd) # elif Propulsion == 2: # raise NotImplementedError # for ObjId in EngineStbd1: # act.MirrorObjectXZ(ObjId) # act.MirrorObjectXZ(PylonStbd1) # for ObjId in EngineStbd2: # act.MirrorObjectXZ(ObjId) # act.MirrorObjectXZ(PylonStbd2) # Build the return assembly (could change this later based on input 'tree': airliner = AirconicsCollection(parts={'Wing_right': Wing, 'Wing_left': Wing2, 'Fuselage': Fus, 'Fin': Fin, 'Tailplane_right': TP, 'Tailplane_left': TP2, 'WBF': WBF}) # Loop over the engines and write all components: for i, eng in enumerate(engines): name = 'engine_right' + str(i+1) airliner.AddPart(eng, name) for i, eng in enumerate(engines_left): name = 'engine_left' + str(i+1) airliner.AddPart(eng, name) return airliner, wires
def myDihedralFunction(Epsilon): """User-defined function describing the variation of dihedral as a function of the leading edge coordinate""" return 7 def myTwistFunction(Epsilon): """User-defined function describing the variation of twist as a function of the leading edge coordinate.""" RootTwist = 0 TipTwist = -2 return RootTwist + Epsilon * TipTwist myChordFunction = act.Generate_InterpFunction([1, 0.33], [0, 1]) @liftingsurface.airfoilfunct def myAirfoilFunction(eps): af_root = Airfoil(SeligProfile='naca63a418') af_tip = Airfoil(SeligProfile='naca63a412') profile_dict = { 'InterpProfile': True, 'Epsilon': eps, 'Af1': af_root, 'Af2': af_tip, 'Eps1': 0, 'Eps2': 1 }