Пример #1
0
from afem.config import Settings
from afem.exchange import ImportVSP
from afem.graphics import Viewer
from afem.smesh import *
from afem.structure import *
from afem.topology import *

Settings.log_to_console()

# v = Viewer()

# Set units to inch.
Settings.set_units('in')

# Import model
fn = r'../models/simple_wing.stp'
vsp_import = ImportVSP(fn)
wing = vsp_import['WingGeom']

# Build structure
wingbox = GroupAPI.create_group('wing box')
fspar = SparByParameters('front spar', 0.15, 0., 0.15, 1., wing).part
rspar = SparByParameters('rear spar', 0.70, 0., 0.70, 1., wing).part
RibByPoints('root rib', fspar.p1, rspar.p1, wing)
RibByPoints('tip rib', fspar.p2, rspar.p2, wing)
RibsAlongCurveByDistance('rib',
                         rspar.cref,
                         30,
                         fspar.shape,
                         rspar.shape,
                         wing,
Пример #2
0
def build_wingbox(wing, params):
    """
    Simple 2 spar wing box with mid spar and aux spar.
    """
    # Set units to inch.
    Settings.set_units('in')

    # SETUP -------------------------------------------------------------------
    _default = {
        'rib spacing': 30.,
        'fspar chord': 0.15,
        'rspar chord': 0.65,
        'root span': 0.05,
        'tip span': 0.925,
        'group name': 'RH main wingbox',
        'mid spar rib': 10,
        'root rib axes': 'xz',
        'part tol': 0.01,
        'build aux': True,
        'aux rib list': ['2', '5', '8'],
        'aux spar xloc': 0.85
    }

    for key in _default:
        if key not in params:
            params[key] = _default[key]

    # Unpack params.
    rib_spacing = params['rib spacing']
    fspar_chord = params['fspar chord']
    rspar_chord = params['rspar chord']
    root_span = params['root span']
    tip_span = params['tip span']
    group_name = params['group name']
    mid_spar_rib = params['mid spar rib']
    build_aux_spar = params['build aux']
    aux_rib_list = params['aux rib list']
    aux_spar_xloc = params['aux spar xloc']

    # BUILD -------------------------------------------------------------------
    GroupAPI.create_group(group_name)

    # Front spar
    fspar = SparByParameters('front spar', fspar_chord, root_span, fspar_chord,
                             tip_span, wing).part

    # Rear spar
    rspar = SparByParameters('rear spar', rspar_chord, root_span, rspar_chord,
                             tip_span, wing).part

    # Root rib
    p1 = fspar.cref.p1
    if not build_aux_spar:
        p2 = rspar.cref.p1
    else:
        p2 = wing.sref.eval(aux_spar_xloc, root_span)
    root = RibByPoints('root rib', p1, p2, wing).part

    # Tip rib
    p1 = fspar.cref.p2
    p2 = rspar.cref.p2
    tip = RibByPoints('tip rib', p1, p2, wing).part

    # Generate points along rear spar and project to front spar to define ribs.
    prear = rspar.points_by_distance(rib_spacing,
                                     d1=rib_spacing,
                                     d2=-rib_spacing)
    pfront = [p.copy() for p in prear]
    rspar_norm = rspar.sref.norm(0, 0)
    fspar.points_to_cref(pfront, rspar_norm)
    i = 1
    ribs = []
    for pf, pr in zip(pfront, prear):
        if pf.is_equal(pr):
            continue
        name = ' '.join(['rib', str(i)])
        rib = RibByPoints(name, pf, pr, wing).part
        ribs.append(rib)
        i += 1

    # Build a mid spar.
    mspar = None
    if mid_spar_rib > 0:
        u1 = root.cref.u1
        u2 = root.cref.invert(rspar.cref.p1)
        dx = root.cref.arc_length(u1, u2)
        p1 = root.point_from_parameter(dx / 2.)
        rib = ribs[mid_spar_rib - 1]
        p2 = rib.point_from_parameter(0.5, is_rel=True)
        mspar = SparByPoints('mid spar', p1, p2, wing).part

    # Aux spar.
    aspar = None
    if build_aux_spar:
        p1 = root.cref.p2
        p2 = rspar.point_from_parameter(0.25, is_rel=True)
        # Find nearest rib point and set equal to aux spar.
        pnts = [rib.cref.p2 for rib in ribs]
        p2 = CheckGeom.nearest_point(p2, pnts)
        indx = pnts.index(p2)
        rib = ribs[indx]
        # Use intersection of the rib and rear spar to define plane for aux
        # spar.
        sref = PlaneByIntersectingShapes(rspar.shape, rib.shape, p1).plane
        aspar = SparByPoints('aux spar', p1, p2, wing, sref).part

    # Build ribs from root rib to front spar.
    root_ribs = []
    if mspar:
        # Fwd of mid spar
        u2 = root.cref.invert(mspar.cref.p1)
        builder = PointsAlongCurveByNumber(root.cref, 3, u2=u2)
        prib = builder.interior_points
        pfront = [p.copy() for p in prib]
        fspar.points_to_cref(pfront, rspar_norm)
        for pf, pr in zip(pfront, prib):
            if pf.is_equal(pr):
                continue
            name = ' '.join(['rib', str(i)])
            rib = RibByPoints(name, pf, pr, wing).part
            if not rib:
                continue
            ribs.append(rib)
            root_ribs.append(rib)
            i += 1

        # Aft of mid spar
        u1 = root.cref.invert(mspar.cref.p1)
        u2 = root.cref.invert(rspar.cref.p1)
        builder = PointsAlongCurveByNumber(root.cref, 3, u1=u1, u2=u2)
        prib = builder.interior_points
        pfront = [p.copy() for p in prib]
        fspar.points_to_cref(pfront, rspar_norm)
        for pf, pr in zip(pfront, prib):
            if pf.is_equal(pr):
                continue
            name = ' '.join(['rib', str(i)])
            rib = RibByPoints(name, pf, pr, wing).part
            if not rib:
                continue
            ribs.append(rib)
            root_ribs.append(rib)
            i += 1

    # Rib at intersection of rear spar and root rib. Use intersection and
    # projected point to define a plane.
    p2 = rspar.cref.p1
    p1 = p2.copy()
    fspar.point_to_cref(p1, rspar_norm)
    sref = PlaneByIntersectingShapes(root.shape, rspar.shape, p1).plane
    RibByPoints('corner rib', p1, p2, wing, sref)

    # Construction geom for center structure.
    root_chord = wing.extract_curve(0, 0, 1, 0)

    # Front center spar.
    p2 = fspar.cref.p1
    p1 = p2.copy()
    ProjectPointToCurve(p1, root_chord, update=True)
    SparByPoints('fc spar', p1, p2, wing)

    # Rear center spar.
    p2 = rspar.cref.p1
    p1 = p2.copy()
    ProjectPointToCurve(p1, root_chord, update=True)
    SparByPoints('rc spar', p1, p2, wing)

    # Mid center spar
    if mid_spar_rib > 0:
        p2 = mspar.cref.p1
        p1 = p2.copy()
        ProjectPointToCurve(p1, root_chord, update=True)
        SparByPoints('center mid spar', p1, p2, wing)

    # Center spar at each root rib intersection
    i = 1
    for rib in root_ribs:
        p2 = rib.cref.p2
        p1 = p2.copy()
        name = ' '.join(['center spar', str(i)])
        ProjectPointToCurve(p1, root_chord, update=True)
        SparByPoints(name, p1, p2, wing)
        i += 1

    # Aux ribs
    if build_aux_spar:
        group_ = GroupAPI.get_active()
        aux_rib_id = 1
        for rib_id in aux_rib_list:
            rib_name = ' '.join(['rib', rib_id])
            rib = group_.get_part(rib_name)
            if not rib:
                continue
            # Since the structure is not joined yet, intersect the rear spar
            # and rib shapes to find the edge(s). Use this edge to define a
            # plane so the aux ribs will line up with the main ribs.
            p1 = rib.cref.p2
            p2 = p1.copy()
            aspar.point_to_cref(p2)
            sref = PlaneByIntersectingShapes(rspar.shape, rib.shape, p2).plane
            aux_rib_name = ' '.join(['aux rib', str(aux_rib_id)])
            RibByPoints(aux_rib_name, p1, p2, wing, sref)
            aux_rib_id += 1

    # JOIN --------------------------------------------------------------------
    # Fuse internal structure and discard faces
    internal_parts = GroupAPI.get_parts(order=True)
    FuseSurfacePartsByCref(internal_parts)
    DiscardByCref(internal_parts)

    # SKIN --------------------------------------------------------------------
    skin = SkinByBody('wing skin', wing, False).part
    skin.set_transparency(0.5)

    # Join the wing skin and internal structure
    skin.fuse(*internal_parts)

    # Discard faces touching reference surface.
    skin.discard_by_dmin(wing.sref_shape, 0.1)

    # Fix skin since it's not a single shell anymore, but a compound of two
    # shells (upper and lower skin).
    skin.fix()

    # Check free edges.
    all_parts = GroupAPI.get_parts(order=True)
    all_shapes = [part.shape for part in all_parts]

    # VOLUMES -----------------------------------------------------------------
    # Demonstrate creating volumes from shapes (i.e., parts). Do not use the
    # intersect option since shapes should be topologically connected already.

    # Volumes using all parts. This generates multiple solids.
    shape1 = VolumesFromShapes(all_shapes).shape

    # Volume using front spar, rear spar, root rib, tip rib, and upper and
    # lower skins. This should produce a single solid since no internal ribs
    #  are provided.
    shape2 = VolumesFromShapes(
        [rspar.shape, fspar.shape, root.shape, tip.shape, skin.shape]).shape
    # Calculate volume.
    print('Volume is ', VolumeProps(shape2).volume)

    # Create a semi-infinite box to cut volume with.
    p0 = wing.sref.eval(0.5, 0.1)
    pln = PlaneByAxes(p0, 'xy').plane
    face = FaceByPlane(pln, -1500, 1500, -1500, 1500).face
    cut_space = ShapeByDrag(face, (0., 0., 500.)).shape

    # Cut the volume with an infinite plane (use a large box for robustness).
    new_shape = CutShapes(shape1, cut_space).shape

    # Calculate cg of cut shape.
    cg = VolumeProps(new_shape).cg
    print('Centroid of cut shape is ', cg)
    print('Volume of cut shape is ', VolumeProps(new_shape).volume)

    # Cut the volume with an infinite plane (use a large box for robustness).
    new_shape = CutShapes(shape2, cut_space).shape

    # Calculate cg of cut shape.
    cg = VolumeProps(new_shape).cg
    print('Centroid of cut shape is ', cg)
    print('Volume of cut shape is ', VolumeProps(new_shape).volume)

    # MESH --------------------------------------------------------------------
    # Initialize
    the_mesh = MeshVehicle(4.)

    # Apply mapped quadrangle to internal structure
    for part_ in internal_parts:
        the_mesh.set_quadrangle_2d(part_.shape)

    # Compute the mesh
    mesh_start = time.time()
    print('Computing mesh...')
    status = the_mesh.compute()
    if not status:
        print('Failed to compute mesh')
    else:
        print('Meshing complete in ', time.time() - mesh_start, ' seconds.')

    gui.add(the_mesh)
    gui.start()
    gui.clear()

    # Uncomment this to export STEP file.
    # from afem.io import StepExport
    # step = StepExport()
    # step.transfer(shape_to_mesh)
    # step.write('wingbox.step')

    return GroupAPI.get_active()