def fix_closed_wire(occwire, occface, tolerance=1e-06): """ This function will try to closed an open wire. Parameters ---------- occwire : OCCwire The OCCwire to be fixed. occface : OCCface The reference OCCface used for closing the OCCwire. tolerance : float, optional The precision for the fix, Default = 1e-06. Returns ------- fixed wire : OCCwire The fixed OCCwire. """ shapefix = ShapeFix_Wire(occwire, occface, tolerance) shapefix.FixClosed() shapefix.FixSmall(True) shapefix.FixDegenerated() shapefix.FixSelfIntersection() shapefix.FixReorder() shapefix.Perform() fix_wire = shapefix.Wire() return fix_wire
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