Esempio n. 1
0
def _FuselageLongitudinalGuideCurves(NoseLengthRatio, TailLengthRatio):
    # Internal function. Defines the four longitudinal curves that outline the
    # fuselage (outer mould line).

    FSVU, FSVL = _AirlinerFuselageSideView(NoseLengthRatio, TailLengthRatio)
    FSVUCurve = rs.AddCurve(FSVU)
    FSVLCurve = rs.AddCurve(FSVL)

    AFPVPort, NoseEndX, TailStartX = _AirlinerFuselagePlanView(
        NoseLengthRatio, TailLengthRatio)

    # Generate plan view
    PlanPortCurve = rs.AddCurve(AFPVPort)

    # How wide is the fuselage?
    (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax) = act.ObjectsExtents(PlanPortCurve)

    # Generate a slightly wider projection surface
    FSVMeanCurve = rs.MeanCurve(FSVUCurve, FSVLCurve)
    RuleLinePort = rs.AddLine((0, 0, 0), (0, -1.1 * abs(Ymax - Ymin), 0))
    FSVMCEP = rs.CurveEndPoint(FSVMeanCurve)
    AftLoftEdgePort = rs.CopyObject(RuleLinePort, FSVMCEP)
    ParallelLoftEdgePort = rs.CopyObject(FSVMeanCurve,
                                         (0, -1.1 * abs(Ymax - Ymin), 0))
    LSPort = rs.AddSweep2((FSVMeanCurve, ParallelLoftEdgePort),
                          (RuleLinePort, AftLoftEdgePort))

    # Project the plan view onto the mean surface
    PortCurve = rs.ProjectCurveToSurface(PlanPortCurve, LSPort, (0, 0, 100))

    # House-keeping
    rs.DeleteObjects([
        LSPort, PlanPortCurve, ParallelLoftEdgePort, RuleLinePort,
        AftLoftEdgePort
    ])

    # Tidy up the mean curve. This is necessary for a smooth result and removing
    # it can render the algorithm unstable. However, FitCurve itself may sometimes
    # be slightly unstable.
    FLength = abs(Xmax - Xmin)  # establish a reference length
    PortCurveSimplified = rs.FitCurve(PortCurve,
                                      distance_tolerance=FLength * 0.001)
    StarboardCurveSimplified = act.MirrorObjectXZ(PortCurveSimplified)

    rs.DeleteObject(PortCurve)

    # Compute the actual end points of the longitudinal curves
    (Xmin, Ymin, Zmin, Xmax1, Ymax,
     Zmax) = act.ObjectsExtents(StarboardCurveSimplified)
    (Xmin, Ymin, Zmin, Xmax2, Ymax,
     Zmax) = act.ObjectsExtents(PortCurveSimplified)
    (Xmin, Ymin, Zmin, Xmax3, Ymax, Zmax) = act.ObjectsExtents(FSVUCurve)
    (Xmin, Ymin, Zmin, Xmax4, Ymax, Zmax) = act.ObjectsExtents(FSVLCurve)
    EndX = min([Xmax1, Xmax2, Xmax3, Xmax4])

    return StarboardCurveSimplified, PortCurveSimplified, FSVUCurve, FSVLCurve, FSVMeanCurve, NoseEndX, TailStartX, EndX
Esempio n. 2
0
def loft_profiles_aux(profiles, rails, is_ruled, is_closed):
    profiles_refs = list([profile.realize()._ref for profile in profiles])
    rails_refs = list([rail.realize()._ref for rail in rails])
    if len(rails_refs) == 0:
        return singleton(
            rh.AddLoftSrf(profiles_refs, None, None, 2 if is_ruled else 0, 0,
                          0, is_closed))
    elif len(rails_refs) == 1:
        return singleton(rh.AddSweep1(rails_refs[0], profiles_refs))
    elif len(rails_refs) == 2:
        return singleton(rh.AddSweep2(rails_refs, profiles_refs))
    elif len(rails_refs) > 2:
        print('Warning: Rhino only supports two rails but were passed {0}'.
              format(len(rails)))
        return singleton(rh.AddSweep2(rails_refs[:2], profiles_refs))
    else:  #Remove?
        raise RuntimeError(
            'Rhino only supports two rails but were passed {0}'.format(
                len(rails)))
Esempio n. 3
0
def TurbofanNacelle(EngineSection,
                    Chord,
                    CentreLocation=[0, 0, 0],
                    ScarfAngle=3,
                    HighlightRadius=1.45,
                    MeanNacelleLength=5.67):
    # The defaults yield a nacelle similar to that of an RR Trent 1000 / GEnx

    HighlightDepth = 0.12 * MeanNacelleLength
    SectionNo = 100

    # Draw the nacelle with the centre of the intake highlight circle in 0,0,0
    rs.EnableRedraw(False)
    Highlight = rs.AddCircle3Pt((0, 0, HighlightRadius),
                                (0, -HighlightRadius, 0),
                                (0, 0, -HighlightRadius))
    HighlightCutterCircle = rs.AddCircle3Pt((0, 0, HighlightRadius * 1.5),
                                            (0, -HighlightRadius * 1.5, 0),
                                            (0, 0, -HighlightRadius * 1.5))

    # Fan disk for CFD boundary conditions
    FanCircle = rs.CopyObject(Highlight, (MeanNacelleLength * 0.25, 0, 0))
    FanDisk = rs.AddPlanarSrf(FanCircle)
    # Aft outflow for CFD boundary conditions
    BypassCircle = rs.CopyObject(Highlight, (MeanNacelleLength * 0.85, 0, 0))
    BypassDisk = rs.AddPlanarSrf(BypassCircle)
    rs.DeleteObjects([FanCircle, BypassCircle])

    # Outflow cone
    TailConeBasePoint = [MeanNacelleLength * 0.84, 0, 0]
    TailConeApex = [MeanNacelleLength * 1.35, 0, 0]
    TailConeRadius = HighlightRadius * 0.782
    TailCone = rs.AddCone(TailConeBasePoint, TailConeApex, TailConeRadius)
    # Spinner cone
    SpinnerConeBasePoint = [MeanNacelleLength * 0.26, 0, 0]
    SpinnerConeApex = [MeanNacelleLength * 0.08, 0, 0]
    SpinnerConeRadius = MeanNacelleLength * 0.09
    Spinner = rs.AddCone(SpinnerConeBasePoint, SpinnerConeApex,
                         SpinnerConeRadius)

    # Tilt the intake
    RotVec = rs.VectorCreate((0, 0, 0), (0, 1, 0))
    Highlight = rs.RotateObject(Highlight, (0, 0, 0), ScarfAngle, axis=RotVec)

    # Set up the disk for separating the intake lip later
    HighlightCutterCircle = rs.RotateObject(HighlightCutterCircle, (0, 0, 0),
                                            ScarfAngle,
                                            axis=RotVec)
    HighlightCutterDisk = rs.AddPlanarSrf(HighlightCutterCircle)
    rs.DeleteObject(HighlightCutterCircle)
    rs.MoveObject(HighlightCutterDisk, (HighlightDepth, 0, 0))

    # Build the actual airfoil sections to define the nacelle
    HighlightPointVector = rs.DivideCurve(Highlight, SectionNo)

    Sections = []
    TailPoints = []
    Rotation = 0
    Twist = 0
    AirfoilSeligName = 'goe613'
    SmoothingPasses = 1

    for HighlightPoint in HighlightPointVector:
        ChordLength = MeanNacelleLength - HighlightPoint.X
        Af = primitives.Airfoil(HighlightPoint, ChordLength, Rotation, Twist,
                                airconics_setup.SeligPath)
        AfCurve, Chrd = primitives.Airfoil.AddAirfoilFromSeligFile(
            Af, AirfoilSeligName, SmoothingPasses)
        rs.DeleteObject(Chrd)
        P = rs.CurveEndPoint(AfCurve)
        list.append(TailPoints, P)
        AfCurve = act.AddTEtoOpenAirfoil(AfCurve)
        list.append(Sections, AfCurve)
        Rotation = Rotation + 360.0 / SectionNo

    list.append(TailPoints, TailPoints[0])

    # Build the actual nacelle OML surface
    EndCircle = rs.AddInterpCurve(TailPoints)
    Nacelle = rs.AddSweep2([Highlight, EndCircle], Sections, closed=True)
    # Separate the lip
    Cowling, HighlightSection = rs.SplitBrep(Nacelle, HighlightCutterDisk,
                                             True)

    # Now build the pylon between the engine and the specified chord on the wing
    CP1 = [
        MeanNacelleLength * 0.26 + CentreLocation[0], CentreLocation[1],
        CentreLocation[2] + HighlightRadius * 0.1
    ]
    CP2 = [
        MeanNacelleLength * 0.4 + CentreLocation[0], CentreLocation[1],
        HighlightRadius * 1.45 + CentreLocation[2]
    ]
    CP3 = rs.CurveEndPoint(Chord)
    rs.ReverseCurve(Chord)
    CP4 = rs.CurveEndPoint(Chord)

    # Move the engine into its actual place on the wing
    rs.MoveObjects(
        [HighlightSection, Cowling, FanDisk, BypassDisk, TailCone, Spinner],
        CentreLocation)

    # Pylon wireframe
    PylonTop = rs.AddInterpCurve([CP1, CP2, CP3, CP4])
    PylonAf = primitives.Airfoil(CP1, MeanNacelleLength * 1.35, 90, 0,
                                 airconics_setup.SeligPath)
    PylonAfCurve, PylonChord = primitives.Airfoil.AddNACA4(
        PylonAf, 0, 0, 12, 3)
    LowerTE = rs.CurveEndPoint(PylonChord)
    PylonTE = rs.AddLine(LowerTE, CP4)

    # Create the actual pylon surface
    PylonLeft = rs.AddNetworkSrf([PylonTop, PylonAfCurve, PylonTE])
    rs.MoveObject(PylonLeft, (0, -CentreLocation[1], 0))
    PylonRight = act.MirrorObjectXZ(PylonLeft)
    rs.MoveObject(PylonLeft, (0, CentreLocation[1], 0))
    rs.MoveObject(PylonRight, (0, CentreLocation[1], 0))
    PylonAfCurve = act.AddTEtoOpenAirfoil(PylonAfCurve)
    PylonAfSrf = rs.AddPlanarSrf(PylonAfCurve)

    # Assigning basic surface properties
    act.AssignMaterial(Cowling, "ShinyBABlueMetal")
    act.AssignMaterial(HighlightSection, "UnpaintedMetal")
    act.AssignMaterial(TailCone, "UnpaintedMetal")
    act.AssignMaterial(FanDisk, "FanDisk")
    act.AssignMaterial(Spinner, "ShinyBlack")
    act.AssignMaterial(BypassDisk, "FanDisk")
    act.AssignMaterial(PylonLeft, "White_composite_external")
    act.AssignMaterial(PylonRight, "White_composite_external")

    # Clean-up
    rs.DeleteObject(HighlightCutterDisk)
    rs.DeleteObjects(Sections)
    rs.DeleteObject(EndCircle)
    rs.DeleteObject(Highlight)
    rs.DeleteObjects([PylonTop, PylonAfCurve, PylonChord, PylonTE])

    rs.Redraw()

    TFEngine = [
        Cowling, HighlightSection, TailCone, FanDisk, Spinner, BypassDisk
    ]
    TFPylon = [PylonLeft, PylonRight, PylonAfSrf]

    return TFEngine, TFPylon
Esempio n. 4
0
def _BuildFuselageOML(NoseLengthRatio, TailLengthRatio, CylindricalMidSection,
                      SimplificationReqd):

    MaxFittingAttempts = 6

    FittingAttempts = -1

    NetworkSrfSettings = [[35, 20, 15, 5, 20], [35, 30, 15, 5, 20],
                          [35, 20, 15, 2, 20], [30, 30, 15, 2, 20],
                          [30, 20, 15, 2, 20], [25, 20, 15, 2, 20],
                          [20, 20, 15, 2, 20], [15, 20, 15, 2, 20]]

    StarboardCurve, PortCurve, FSVUCurve, FSVLCurve, FSVMeanCurve, NoseEndX, TailStartX, EndX = _FuselageLongitudinalGuideCurves(
        NoseLengthRatio, TailLengthRatio)

    while FittingAttempts <= MaxFittingAttempts:

        FittingAttempts = FittingAttempts + 1

        # Construct array of cross section definition frames
        SX0 = 0
        Step01 = NetworkSrfSettings[FittingAttempts][0]
        SX1 = 0.04 * NoseEndX
        Step12 = NetworkSrfSettings[FittingAttempts][1]
        SX2 = SX1 + 0.25 * NoseEndX
        Step23 = NetworkSrfSettings[FittingAttempts][2]
        SX3 = NoseEndX
        Step34 = NetworkSrfSettings[FittingAttempts][3]
        SX4 = TailStartX
        Step45 = NetworkSrfSettings[FittingAttempts][4]
        SX5 = EndX

        print "Attempting network surface fit with network density setup ", NetworkSrfSettings[
            FittingAttempts][:]

        Stations01 = act.pwfrange(SX0, SX1, max([Step01, 2]))
        Stations12 = act.pwfrange(SX1, SX2, max([Step12, 2]))
        Stations23 = act.pwfrange(SX2, SX3, max([Step23, 2]))
        Stations34 = act.pwfrange(SX3, SX4, max([Step34, 2]))
        Stations45 = act.pwfrange(SX4, SX5, max([Step45, 2]))

        StationRange = Stations01[:
                                  -1] + Stations12[:
                                                   -1] + Stations23[:
                                                                    -1] + Stations34[:
                                                                                     -1] + Stations45
        C = []
        FirstTime = True
        for XStation in StationRange:
            P = rs.PlaneFromPoints((XStation, 0, 0), (XStation, 1, 0),
                                   (XStation, 0, 1))
            IP1 = rs.PlaneCurveIntersection(P, StarboardCurve)
            IP2 = rs.PlaneCurveIntersection(P, FSVUCurve)
            IP3 = rs.PlaneCurveIntersection(P, PortCurve)
            IP4 = rs.PlaneCurveIntersection(P, FSVLCurve)
            IPcentre = rs.PlaneCurveIntersection(P, FSVMeanCurve)
            IPoint1 = rs.AddPoint(IP1[0][1])
            IPoint2 = rs.AddPoint(IP2[0][1])
            IPoint3 = rs.AddPoint(IP3[0][1])
            IPoint4 = rs.AddPoint(IP4[0][1])
            IPointCentre = rs.AddPoint(IPcentre[0][1])
            PseudoDiameter = abs(IP4[0][1].Z - IP2[0][1].Z)
            if CylindricalMidSection and NoseEndX < XStation < TailStartX:
                # Ensure that the parallel section of the fuselage is cylindrical
                # if CylindricalMidSection is True
                print "Enforcing circularity in the central section..."
                if FirstTime:
                    PseudoRadius = PseudoDiameter / 2
                    FirstTime = False
                Pc = rs.PointCoordinates(IPointCentre)
                P1 = P2 = P3 = Pc
                P1 = rs.PointAdd(P1, (0, PseudoRadius, 0))
                P2 = rs.PointAdd(P2, (0, 0, PseudoRadius))
                P3 = rs.PointAdd(P3, (0, -PseudoRadius, 0))
                c = rs.AddCircle3Pt(P1, P2, P3)
            else:
                c = rs.AddInterpCurve(
                    [IPoint1, IPoint2, IPoint3, IPoint4, IPoint1], knotstyle=3)
                # Once CSec is implemented in Rhino Python, this could be replaced
            rs.DeleteObjects(
                [IPoint1, IPoint2, IPoint3, IPoint4, IPointCentre])
            list.append(C, c)

        # Fit fuselage external surface
        CurveNet = []
        for c in C[1:]:
            list.append(CurveNet, c)
        list.append(CurveNet, FSVUCurve)
        list.append(CurveNet, PortCurve)
        list.append(CurveNet, FSVLCurve)
        list.append(CurveNet, StarboardCurve)
        FuselageOMLSurf = rs.AddNetworkSrf(CurveNet)
        rs.DeleteObjects(C)

        if not (FuselageOMLSurf == None):
            print "Network surface fit succesful on attempt ", FittingAttempts + 1
            FittingAttempts = MaxFittingAttempts + 1  # Force an exit from 'while'

    # If all attempts at fitting a network surface failed, we attempt a Sweep2
    if FuselageOMLSurf == None:
        print "Failed to fit network surface to the external shape of the fuselage"
        print "Attempting alternative fitting method, quality likely to be low..."

        try:
            FuselageOMLSurf = rs.AddSweep2([FSVUCurve, FSVLCurve], C[:])
        except:
            FuselageOMLSurf = False

        SimplificationReqd = True  # Enforce simplification
        if not (FuselageOMLSurf):
            print "Alternative fitting method failed too. Out of ideas."

    if FuselageOMLSurf and SimplificationReqd:
        rs.UnselectAllObjects()
        rs.SelectObject(FuselageOMLSurf)
        ToleranceStr = str(0.0005 * EndX)
        print "Smoothing..."
        rs.Command("FitSrf " + ToleranceStr)
        rs.UnselectAllObjects()

    # Compute the stern point coordinates of the fuselage
    Pu = rs.CurveEndPoint(FSVUCurve)
    Pl = rs.CurveEndPoint(FSVLCurve)
    SternPoint = [Pu.X, Pu.Y, 0.5 * (Pu.Z + Pl.Z)]

    rs.DeleteObjects(
        [FSVUCurve, FSVLCurve, PortCurve, StarboardCurve, FSVMeanCurve])

    return FuselageOMLSurf, SternPoint
Esempio n. 5
0
    def _BuildLS(self, ChordFactor, ScaleFactor):
        # Generates a tentative lifting surface, given the general, nondimensio-
        # nal parameters of the object (variations of chord length, dihedral, etc.)
        # and the two scaling factors.

        LEPoints = self._GenerateLeadingEdge()

        Sections = []
        ProjectedSections = []
        TEPoints_u = []
        TEPoints_l = []

        for i, LEP in enumerate(LEPoints):
            Eps = float(i)/self.SegmentNo
            Airfoil, Chrd = self.AirfoilFunct(Eps, LEP, self.ChordFunct, ChordFactor, self.DihedralFunct, self.TwistFunct)
            list.append(Sections, Airfoil)

            Pr = rs.ProjectCurveToSurface(Chrd,self.XoY_Plane,self.ProjVectorZ)
            list.append(ProjectedSections, Pr)

            list.append(TEPoints_l, rs.CurveEndPoint(Airfoil))
            list.append(TEPoints_u, rs.CurveStartPoint(Airfoil))

            rs.DeleteObjects(Chrd)

        LS = rs.AddLoftSrf(Sections,loft_type=self.LooseSurf)

        if LS==None:
            # Failed to fit loft surface. Try another fitting algorithm
            TECurve_u = rs.AddInterpCurve(TEPoints_u)
            TECurve_l = rs.AddInterpCurve(TEPoints_l)

            rails = []
            list.append(rails, TECurve_u)
            list.append(rails, TECurve_l)

            # Are the first and last curves identical?
            # AddSweep fails if they are, so if that is the case, one is skipped
            CDev = rs.CurveDeviation(Sections[0],Sections[-1])
            if CDev==None:
                shapes = Sections
                LS = rs.AddSweep2(rails, shapes, False)
            else:
                shapes = Sections[:-1]
                LS = rs.AddSweep2(rails, shapes, True)

            rs.DeleteObjects(rails)
            rs.DeleteObjects([TECurve_u, TECurve_l])

        WingTip = None

        if self.TipRequired:
            TipCurve = Sections[-1]
            TipCurve = act.AddTEtoOpenAirfoil(TipCurve)
            WingTip = rs.AddPlanarSrf(TipCurve)
            rs.DeleteObject(TipCurve)

        # Calculate projected area
        # In some cases the projected sections cannot all be lofted in one go
        # (it happens when parts of the wing fold back onto themselves), so
        # we loft them section by section and we compute the area as a sum.
        LSP_area = 0
        # Attempt to compute a projected area
        try:
            for i, LEP in enumerate(ProjectedSections):
                if i < len(ProjectedSections)-1:
                    LSPsegment = rs.AddLoftSrf(ProjectedSections[i:i+2])
                    SA = rs.SurfaceArea(LSPsegment)
                    rs.DeleteObject(LSPsegment)
                    LSP_area = LSP_area + SA[0]
        except:
            print "Failed to compute projected area. Using half of surface area instead."
            LS_area = rs.SurfaceArea(LS)
            LSP_area = 0.5*LS_area[0]

        BB = rs.BoundingBox(LS)
        if BB:
            ActualSemiSpan = BB[2].Y - BB[0].Y
        else:
            ActualSemiSpan = 0.0

        # Garbage collection
        rs.DeleteObjects(Sections)
        try:
            rs.DeleteObjects(ProjectedSections)
        except:
            print "Cleanup: no projected sections to delete"
        rs.DeleteObjects(LEPoints)


        # Scaling
        Origin = rs.AddPoint([0,0,0])
        ScaleXYZ = (ScaleFactor, ScaleFactor, ScaleFactor)
        LS = rs.ScaleObject(LS, Origin, ScaleXYZ)
        if self.TipRequired and WingTip:
            WingTip = rs.ScaleObject(WingTip, Origin, ScaleXYZ)

        rs.DeleteObject(Origin)

        ActualSemiSpan = ActualSemiSpan*ScaleFactor
        LSP_area = LSP_area*ScaleFactor**2.0
        RootChord = (self.ChordFunct(0)*ChordFactor)*ScaleFactor
        AR = ((2.0*ActualSemiSpan)**2.0)/(2*LSP_area)

        return LS, ActualSemiSpan, LSP_area, RootChord, AR, WingTip
Esempio n. 6
0
def RunCommand(is_interactive):
    global params

    center = rs.GetPoint(message="Select center point")

    n = rs.GetInteger(message="Number of teeth",
                      number=params["n"], minimum=4)

    m = rs.GetReal(message="Gear module",
                   number=params["m"])

    pa = rs.GetReal(message="Pressure angle",
                    number=params["pa"], minimum=0, maximum=45)

    ha = rs.GetReal(message="Helix angle",
                    number=params["ha"], minimum=-45, maximum=45)

    t = rs.GetReal(message="Thickness",
                   number=params["t"], minimum=0)

    bool_opts = rs.GetBoolean(message="Output options",
                              items=(("PitchCylinder", "No", "Yes"),),
                              defaults=(params["pc"],))

    if None in [center, n, m, pa, ha, t, bool_opts]:
        return 1  # Cancel

    pc = bool_opts[0]

    params["n"] = n
    params["m"] = m
    params["pa"] = pa
    params["ha"] = ha
    params["t"] = t
    params["pc"] = pc

    cplane = rs.ViewCPlane()  # Get current CPlane
    cplane = rs.MovePlane(cplane, center)
    xform = rs.XformChangeBasis(cplane, rs.WorldXYPlane())

    rs.EnableRedraw(False)
    old_plane = rs.ViewCPlane(plane=rs.WorldXYPlane())

    gear = generate_gear_crv(teeth=params["n"],
                             module=params["m"],
                             pressure_angle=params["pa"])

    pitch = abs((n * m * pi) / tan(radians(ha)))
    turns = t / pitch

    if ha < 0:
        # Left handed helix
        turns = -turns

    centerline = rs.AddLine([0, 0, 0], [0, 0, t])
    helix = rs.AddSpiral([0, 0, 0],
                         [0, 0, t],
                         pitch=pitch,
                         turns=turns,
                         radius0=(m * n) / 2)

    helical_gear_srf = rs.AddSweep2(rails=[centerline, helix], shapes=[gear])
    rs.DeleteObjects([centerline, helix, gear])

    rs.ViewCPlane(plane=old_plane)
    rs.TransformObjects(helical_gear_srf, xform)

    if pc:
        circle = generate_pitch_circle_crv(teeth=params["n"],
                                           module=params["m"])
        pitch_cyl_srf = rs.ExtrudeCurveStraight(circle,
                                                start_point=[0, 0, 0],
                                                end_point=[0, 0, t])
        rs.TransformObjects(pitch_cyl_srf, xform)
        rs.DeleteObject(circle)
        rs.SelectObjects([helical_gear_srf, pitch_cyl_srf])
    else:
        rs.SelectObjects(helical_gear_srf)

    rs.EnableRedraw(True)

    return 0  # Success