Esempio n. 1
0
    def face(self):
        """
        Get the face the point is on.

        :return: The face.
        :rtype: afem.topology.entities.Face
        """
        return Face(self._tool.Face())
Esempio n. 2
0
    def has_ancestor_face2(self, edge):
        """
        Get the ancestor face on the intersection edge on the second shape
        if available.

        :param afem.topology.entities.Edge edge: The edge.

        :return: *True* and the face if available, *False* and *None* if not.
        :rtype: tuple(bool, afem.topology.entities.Face or None)
        """
        f = TopoDS_Face()
        if self._bop.HasAncestorFaceOn2(edge.object, f):
            return True, Face(f)
        return False, None
Esempio n. 3
0
    def rebuild_wing_solid(srfs, divide_closed=True, reloft=False, tol=0.01):
        """
        Rebuild a solid shape from the OpenVSP wing surface(s). If only one
        surface is provided then it is assumed that a single surface models the
        OML and it will be split and modified at the root, tip, and trailing
        edge. This single surface should have similar form and
        parametrization as the original OpenVSP surface. If more than once
        surface is provided then it is assumed that the surfaces were split
        during OpenVSP export and are simply sewn together to form the solid.

        :param srfs: The wing surface(s) used to rebuild the solid.
        :type srfs: collections.Sequence(afem.geometry.entities.Surface)
        :param bool divide_closed: Option to divide closed faces.
        :param bool reloft: For wings that are not split, this option will
            extract isocurves at each spanwise cross section, tessellate the
            curve using *tol*, and then approximate the section using a C1
            continuous curve. These curves are then used to generate a new
            wing surface. This method is experimental.
        :param float tol: Tolerance for approximation if
            *bspline_restrict* or *reloft* is *True*.

        :return: The new solid.
        :rtype: afem.topology.entities.Solid

        :raise ValueError: If no surfaces are provided.
        """
        faces = [Face.by_surface(s) for s in srfs]
        compound = Compound.by_shapes(faces)

        nsrfs = len(srfs)
        if nsrfs == 1:
            solid, _ = _process_unsplit_wing(compound, divide_closed, reloft,
                                             tol)
            return solid
        elif nsrfs > 1:
            solid, _ = _build_solid(compound, divide_closed)
            return solid
        else:
            raise ValueError('No surfaces provided.')
Esempio n. 4
0
 def __init__(self, face, v):
     v = CheckGeom.to_vector(v)
     builder = BRepPrimAPI_MakePrism(face.object, v)
     self._solid = Solid(builder.Shape())
     self._f1 = Face(builder.FirstShape())
     self._f2 = Face(builder.LastShape())
Esempio n. 5
0
 def __init__(self, edge, v):
     v = CheckGeom.to_vector(v)
     builder = BRepPrimAPI_MakePrism(edge.object, v)
     self._f = Face(builder.Shape())
     self._e1 = Edge(builder.FirstShape())
     self._e2 = Edge(builder.LastShape())
Esempio n. 6
0
 def __init__(self, wire):
     if isinstance(wire, Curve):
         wire = Wire.by_curve(wire)
     elif isinstance(wire, Edge):
         wire = Wire.by_edge(wire)
     self._f = Face(BRepBuilderAPI_MakeFace(wire.object, True).Face())
Esempio n. 7
0
 def __init__(self, pln, umin, umax, vmin, vmax):
     builder = BRepBuilderAPI_MakeFace(pln.gp_pln, umin, umax, vmin, vmax)
     self._f = Face(builder.Face())
Esempio n. 8
0
 def bottom_face(self):
     """
     :return: The bottom face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.BottomFace())
Esempio n. 9
0
 def face(self):
     """
     :return: The sphere as a face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.Face())
Esempio n. 10
0
 def face(self):
     """
     :return: The lateral face of the cylinder
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.Face())
Esempio n. 11
0
 def top_face(self):
     """
     :return: The top face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.TopFace())
Esempio n. 12
0
 def right_face(self):
     """
     :return: The right face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.RightFace())
Esempio n. 13
0
 def left_face(self):
     """
     :return: The left face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.LeftFace())
Esempio n. 14
0
 def front_face(self):
     """
     :return: The front face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.FrontFace())
Esempio n. 15
0
 def back_face(self):
     """
     :return: The back face.
     :rtype: afem.topology.entities.Face
     """
     return Face(self._builder.BackFace())
Esempio n. 16
0
def _build_solid(compound, divide_closed):
    """
    Try to build a solid from the OpenVSP compound of faces.

    :param afem.topology.entities.Compound compound: The compound.
    :param bool divide_closed: Option to divide closed faces.

    :return: The solid.
    :rtype: afem.topology.entities.Solid
    """
    # Get all the faces in the compound. The surfaces must be split. Discard
    # any with zero area.
    faces = []
    for face in compound.faces:
        area = SurfaceProps(face).area
        if area > 1.0e-7:
            faces.append(face)

    # Replace any planar B-Spline surfaces with planes.
    non_planar_faces = []
    planar_faces = []
    for f in faces:
        srf = f.surface
        try:
            pln = srf.as_plane()
            if pln:
                w = f.outer_wire
                # Fix the wire because they are usually degenerate edges in
                # the planar end caps.
                builder = BRepBuilderAPI_MakeWire()
                for e in w.edges:
                    if LinearProps(e).length > 1.0e-7:
                        builder.Add(e.object)
                w = builder.Wire()
                fix = ShapeFix_Wire()
                fix.Load(w)
                fix.SetSurface(pln.object)
                fix.FixReorder()
                fix.FixConnected()
                fix.FixEdgeCurves()
                fix.FixDegenerated()
                w = Wire(fix.WireAPIMake())
                fnew = Face.by_wire(w)
                planar_faces.append(fnew)
            else:
                non_planar_faces.append(f)
        except RuntimeError:
            logger.info('Failed to check for planar face...')
            non_planar_faces.append(f)

    # Make a compound of the faces
    shape = Compound.by_shapes(non_planar_faces + planar_faces)

    # Split closed faces
    if divide_closed:
        shape = DivideClosedShape(shape).shape

    # Sew shape
    sewn_shape = SewShape(shape).sewed_shape
    if isinstance(sewn_shape, Face):
        sewn_shape = sewn_shape.to_shell()

    # Attempt to unify planar domains
    shell = UnifyShape(sewn_shape).shape

    # Make solid
    if not isinstance(shell, Shell):
        logger.info('\tA valid shell was not able to be generated.')
        check = CheckShape(shell)
        if not check.is_valid:
            logger.info('\tShape errors:')
            check.log_errors()
        return shell, check.invalid_shapes

    solid = Solid.by_shell(shell)

    # Limit tolerance
    FixShape.limit_tolerance(solid)

    # Check the solid and attempt to fix
    invalid = []
    check = CheckShape(solid)
    if not check.is_valid:
        logger.info('\tFixing the solid...')
        solid = FixShape(solid).shape
        check = CheckShape(solid)
        if not check.is_valid:
            logger.info('\t...solid could not be fixed.')
            logger.info('\tShape errors:')
            check.log_errors()
            failed = check.invalid_shapes
            invalid += failed
    else:
        tol = solid.tol_avg
        logger.info(
            '\tSuccessfully generated solid with tolerance={}'.format(tol))

    return solid, invalid
Esempio n. 17
0
def _process_unsplit_wing(compound, divide_closed, reloft, tol):
    # Process a wing that was generated without "Split Surfs" option.

    faces = compound.faces
    if len(faces) != 1:
        return None, None
    face = faces[0]

    # Get the surface.
    master_surf = face.surface
    # master_surf = NurbsSurface(master_surf.object)
    uknots, vknots = master_surf.uknots, master_surf.vknots
    vsplit = master_surf.local_to_global_param('v', 0.5)

    # Segment off the end caps and the trailing edges.
    u1, u2 = uknots[1], uknots[-2]
    v1, v2 = vknots[1], vknots[-2]
    s1 = master_surf.copy()
    s1.segment(u1, u2, v1, v2)

    # Reloft the surface by tessellating a curve at each spanwise knot. This
    # enforces C1 continuity but assumes linear spanwise wing which may not
    # support blending wing sections in newer versions of OpenVSP. Also, since
    # the tessellated curves may not match up to the wing end caps making
    # sewing unreliable, flat end caps are assumed.
    if reloft:
        s1 = _reloft_wing_surface(s1, tol)

        # Generate new flat end caps using isocurves at the root and tip of
        # this new surface
        c0 = s1.v_iso(s1.v1)
        c1 = s1.v_iso(s1.v2)
        e0 = Edge.by_curve(c0)
        e1 = Edge.by_curve(c1)
        w0 = Wire.by_edge(e0)
        w1 = Wire.by_edge(e1)
        f0 = Face.by_wire(w0)
        f1 = Face.by_wire(w1)

        # Make faces of surfaces
        f = Face.by_surface(s1)
        new_faces = [f, f0, f1]
    else:
        # Reparamterize knots in spanwise direction to be chord length instead
        # of uniform. Use isocurve at quarter-chord to determine knot values.
        # This only works as long as surfaces are linear.
        c0 = s1.u_iso(s1.u1)
        c0.segment(vsplit, c0.u2)
        qc_u = PointFromParameter(c0, vsplit, 0.25 * c0.length).parameter
        c = s1.v_iso(qc_u)
        pnts = [c.eval(u) for u in c.knots]
        new_uknots = geom_utils.chord_parameters(pnts, 0., 1.)
        s1.set_uknots(new_uknots)

        # Segment off end caps
        u1, u2 = uknots[0], uknots[1]
        v1, v2 = vknots[1], vsplit
        s2 = master_surf.copy()
        s2.segment(u1, u2, v1, v2)

        u1, u2 = uknots[0], uknots[1]
        v1, v2 = vsplit, vknots[-2]
        s3 = master_surf.copy()
        s3.segment(u1, u2, v1, v2)

        u1, u2 = uknots[-2], uknots[-1]
        v1, v2 = vknots[1], vsplit
        s4 = master_surf.copy()
        s4.segment(u1, u2, v1, v2)

        u1, u2 = uknots[-2], uknots[-1]
        v1, v2 = vsplit, vknots[-2]
        s5 = master_surf.copy()
        s5.segment(u1, u2, v1, v2)

        # Make faces of surfaces
        new_faces = []
        for s in [s1, s2, s3, s4, s5]:
            f = Face.by_surface(s)
            new_faces.append(f)

    # Segment off TE.
    u1, u2 = uknots[0], uknots[-1]
    v1, v2 = vknots[0], vknots[1]
    s6 = master_surf.copy()
    s6.segment(u1, u2, v1, v2)

    u1, u2 = uknots[0], uknots[-1]
    v1, v2 = vknots[-2], vknots[-1]
    s7 = master_surf.copy()
    s7.segment(u1, u2, v1, v2)

    # Split the TE surface at each u-knot.
    usplits = occ_utils.to_tcolstd_hseq_real(uknots[1:-1])

    split = ShapeUpgrade_SplitSurface()
    split.Init(s6.object)
    split.SetUSplitValues(usplits)
    split.Perform()
    comp_surf1 = split.ResSurfaces()

    split = ShapeUpgrade_SplitSurface()
    split.Init(s7.object)
    split.SetUSplitValues(usplits)
    split.Perform()
    comp_surf2 = split.ResSurfaces()

    # For each patch in the composite surfaces create a face.
    for i in range(1, comp_surf1.NbUPatches() + 1):
        for j in range(1, comp_surf1.NbVPatches() + 1):
            hpatch = comp_surf1.Patch(i, j)
            f = BRepBuilderAPI_MakeFace(hpatch, 0.).Face()
            new_faces.append(f)

    for i in range(1, comp_surf2.NbUPatches() + 1):
        for j in range(1, comp_surf2.NbVPatches() + 1):
            hpatch = comp_surf2.Patch(i, j)
            f = BRepBuilderAPI_MakeFace(hpatch, 0.).Face()
            new_faces.append(f)

    # Put all faces into a compound a generate solid.
    new_compound = Compound.by_shapes(new_faces)

    return _build_solid(new_compound, divide_closed)
Esempio n. 18
0
 def __init__(self, srf, tol=1.0e-7):
     self._f = Face(BRepBuilderAPI_MakeFace(srf.object, tol).Face())