def __init__(self, groups, fuzzy_val=None, include_subgroup=True): if len(groups) < 2: raise ValueError('Not enough groups to fuse. Need at least ' 'two.') bop = FuseShapes(fuzzy_val=fuzzy_val) groups = list(groups) parts1 = groups[0].get_parts(include_subgroup) shapes1 = [part.shape for part in parts1] shape1 = CompoundByShapes(shapes1).compound bop.set_args([shape1]) tools = [] other_parts = [] for group in groups[1:]: parts = group.get_parts(include_subgroup) other_parts += parts shapes = [part.shape for part in parts] shape = CompoundByShapes(shapes).compound tools.append(shape) bop.set_tools(tools) bop.build() all_parts = parts1 + other_parts all_shapes = [part.shape for part in all_parts] rebuild = RebuildShapesByTool(all_shapes, bop) for part in all_parts: new_shape = rebuild.new_shape(part.shape) part.set_shape(new_shape) self._bop = bop
def debug(self, path='.'): """ Export files for debugging Boolean operations. :param path: :return: """ # Generate a suffix using timestamp now = datetime.now() timestamp = str(now.timestamp()) # Operation name for prefix op = str(self.__class__.__name__) # Info file fn = ''.join([path, '/', op, '.info.', timestamp, '.txt']) info = open(fn, 'w') info.write('Date (M-D-Y): {}-{}-{}\n'.format(now.month, now.day, now.year)) info.write('Operation: {}\n'.format(op)) info.write('Parallel: {}\n'.format(self._bop.RunParallel())) info.write('Fuzzy value: {}\n'.format(self._bop.FuzzyValue())) info.write('Nondestructive: {}\n'.format(self._bop.NonDestructive())) # Errors and warnings report msg_report = self._bop.GetReport() for gravity in _gravities: msg_list = msg_report.GetAlerts(gravity) if msg_list.Size() == 0: continue info.write('Messages:\n') for msg in msg_list: info.write('\t{}\n'.format(msg.GetMessageKey())) info.close() # Avoid circular imports from afem.exchange.brep import write_brep from afem.topology.create import CompoundByShapes # Arguments args = self.arguments if args: shape1 = CompoundByShapes(args).compound fn = ''.join([path, '/', op, '.shape1.', timestamp, '.brep']) write_brep(shape1, fn) # Tools tools = self.tools if tools: shape2 = CompoundByShapes(tools).compound fn = ''.join([path, '/', op, '.shape2.', timestamp, '.brep']) write_brep(shape2, fn)
def fuse(self, *other_parts): """ Fuse with other surface parts and rebuild both. :param afem.structure.entities.SurfacePart other_parts: The other part(s). :return: *True* if fused, *False* if not. :rtype: bool """ # Putting the other parts in a compound avoids fusing them to each # other other_shapes = [part.shape for part in other_parts] other_compound = CompoundByShapes(other_shapes).compound fuse = FuseShapes(self._shape, other_compound) if not fuse.is_done: return False # Rebuild the part shapes parts = [self] + list(other_parts) shapes = [part.shape for part in parts] rebuild = RebuildShapesByTool(shapes, fuse) for part in parts: new_shape = rebuild.new_shape(part.shape) part.set_shape(new_shape) return True
def shared_edges(parts, others, as_compound=False): """ Collect the shared edges between two sets of parts. :param collections.Sequence(afem.structure.entities.Part) parts: The first set of parts. :param collections.Sequence(afem.structure.entities.Part) others: The other set of parts. :param bool as_compound: Option to return the shared edges as a compound. :return: List of shared edges. :rtype: list(afem.topology.entities.Edge) or afem.topology.entities.Compound """ shape1 = CompoundByShapes([part.shape for part in parts]).compound shape2 = CompoundByShapes([part.shape for part in others]).compound return shape1.shared_edges(shape2, as_compound)
def parts_to_compound(parts): """ Convert the list of parts into a single compound using each of their shapes. :param collections.Sequence(afem.structure.entities.Part) parts: The parts. :return: The compound. :rtype: afem.topology.entities.Compound """ return CompoundByShapes([part.shape for part in parts]).compound
def add_edges_on_face(self, e, f): """ :param collections.Sequence(afem.topology.entities.Edge) e: The edges. :param afem.topology.entities.Face f: The face. :return: None """ # Avoid circular imports from afem.topology.create import CompoundByShapes cmp = CompoundByShapes(e).compound self._bop.Add(cmp.object, f.object)
def as_compound(self, include_subgroup=True): """ Build a Compound from all the parts of the group. :param bool include_subgroup: Option to recursively include parts from any subgroups. :return: The parts as a compound. :rtype: afem.topology.entities.Compound """ parts = self.get_parts(include_subgroup) shapes = [part.shape for part in parts] return CompoundByShapes(shapes).compound
def get_shape(self, include_subgroup=True): """ Get a shape derived from all parts in the group. This puts all the parts into a single compound which could be used as the master shape for the meshing process. :param bool include_subgroup: Option to recursively include parts from any subgroups. :return: The part shapes as a compound. :rtype: afem.topology.entities.Compound """ parts = self.get_parts(include_subgroup) shapes = [part.shape for part in parts] return CompoundByShapes(shapes).compound
def shared_edges(self, other, as_compound=False): """ Get edges shared between the two parts. :param other: The other part or shape. :type other: afem.structure.entities.Part or afem.topology.entities.Shape :param bool as_compound: Option to return the shared edges in a compound. :return: Shared edges. :rtype: list(afem.topology.entities.Edge) or afem.topology.entities.Compound """ other = shape_of_entity(other) edges = self._shape.shared_edges(other) if not as_compound: return edges return CompoundByShapes(edges).compound
def face_compound(self): """ :return: A compound containing the faces. :rtype: afem.topology.entities.Compound """ return CompoundByShapes(self._shape.faces).compound
def edge_compound(self): """ :return: A compound containing the part edges. :rtype: afem.topology.entities.Compound """ return CompoundByShapes(self.edges).compound