def generate(self, design): operation_ref, output_index = self.operation_links['parent'][0] operation_output = design.op_from_ref(operation_ref).output[output_index] generic = operation_output.generic_laminate() laminates = popupcad.algorithms.body_detection.find(generic) self.output = [] for ii, item in enumerate(laminates): self.output.append(OperationOutput(item,'Body {0:d}'.format(ii),self)) self.output.insert(0, self.output[0])
def generate(self, design): import popupcad import popupcad.algorithms.removability as removability sheet_id, sheet_output = self.operation_links['sheet'][0] device_id, device_output = self.operation_links['device'][0] sheet = design.op_from_ref(sheet_id).output[sheet_output].csg device = design.op_from_ref(device_id).output[device_output].csg removable_both, removable_up, removable_down = removability.generate_removable_scrap( device, sheet, device_buffer=self.values[0] * popupcad.csg_processing_scaling) a = OperationOutput(removable_both, 'removable_both', self) b = OperationOutput(removable_up, 'removable_up', self) c = OperationOutput(removable_down, 'removable_down', self) self.output = [a, a, b, c]
def generate(self, design): operation_ref, output_index = self.operation_links['parent'][0] generic = design.op_from_ref( operation_ref).output[output_index].generic_laminate() layerdef = design.return_layer_definition() new_csgs = popupcad.algorithms.manufacturing_functions.find_rigid( generic, layerdef) self.output = [] for ii, item in enumerate(new_csgs): self.output.append( OperationOutput(item, 'Rigid Body {0:d}'.format(ii), self)) self.output.insert(0, self.output[0])
def generate(self, design): operation_ref, output_index = self.operation_links['parent'][0] import popupcad ls1 = design.op_from_ref(operation_ref).output[output_index].csg if self.keepout_type == self.keepout_types.laser_keepout: keepout = popupcad.algorithms.keepout.laserkeepout(ls1) elif self.keepout_type == self.keepout_types.mill_keepout: keepout = popupcad.algorithms.keepout.millkeepout(ls1) elif self.keepout_type == self.keepout_types.mill_flip_keepout: keepout = popupcad.algorithms.keepout.millflipkeepout(ls1) else: raise Exception support, k3 = popupcad.algorithms.web.autosupport( ls1, keepout, design.return_layer_definition(), self.values[0] * popupcad.csg_processing_scaling, self.values[1] * popupcad.csg_processing_scaling, 1e-5 * popupcad.csg_processing_scaling) a = OperationOutput(support, 'support', self) b = OperationOutput(keepout, 'cut line', self) c = OperationOutput(k3, 'cut area', self) self.output = [a, a, b, c]
def generate(self, design): operation_ref, output_index = self.operation_links['parent'][0] import popupcad ls1 = design.op_from_ref(operation_ref).output[output_index].csg if self.keepout_type == self.keepout_types.laser_keepout: keepout = popupcad.algorithms.keepout.laserkeepout(ls1) elif self.keepout_type == self.keepout_types.mill_keepout: keepout = popupcad.algorithms.keepout.millkeepout(ls1) elif self.keepout_type == self.keepout_types.mill_flip_keepout: keepout = popupcad.algorithms.keepout.millflipkeepout(ls1) sheet, outer_web, inner_elements, buffered_keepout = popupcad.algorithms.web.generate_web( ls1, keepout, design.return_layer_definition(), (self.values[0] + self.values[1]) * popupcad.csg_processing_scaling, self.values[1] * popupcad.csg_processing_scaling) a = OperationOutput(outer_web, 'Web', self) b = OperationOutput(sheet, 'Sheet', self) c = OperationOutput(inner_elements, 'Inner Scrap', self) d = OperationOutput(buffered_keepout, 'Removed Material', self) self.output = [a, b, c, d]
def operate(self, design): design_copy = design # design_copy.reprocessoperations() part_to_insert = design_copy.operations[design_copy.operation_index(self.part_opref)] sheet_to_insert_into = design_copy.operations[design_copy.operation_index(self.sheet_opref)] release_to_insert_into = design_copy.operations[design_copy.operation_index(self.release_opref)] # build the op_links, then auto make the operation op = part_to_insert op_ref = op.id op_links = {'parent': [(op_ref, op.getoutputref())]} new_web = AutoWeb4(op_links,[self.support_offset,0],MultiValueOperation3.keepout_types.laser_keepout) new_web.setcustomname(op.name) # support = OperationOutput(new_web.output[1], "support", self) design_copy.addoperation(new_web) new_web.generate(design_copy) ######################## generate the same size construction line somewhere in the sheet file # get geom for line parts_bounding_box = new_web.output[1].generic_laminate().getBoundingBox() # parts_bounding_box = support.generic_laminate().getBoundingBox() # make the sketch construction_geom_hinge = Sketch.new() tmp_geom = [(parts_bounding_box[0],parts_bounding_box[1]), (parts_bounding_box[0],parts_bounding_box[3])] construction_line = GenericLine.gen_from_point_lists(tmp_geom,[],construction=False) construction_geom_hinge.addoperationgeometries([construction_line]) # add sketch to sketch list design_copy.sketches[construction_geom_hinge.id] = construction_geom_hinge ######################## generate the external transform geometry in the sheet # center the locate line top left as origin position_hinge = (-tmp_geom[0][0],-tmp_geom[0][1]) locate_lines = [(x + position_hinge[0], y + position_hinge[1]) for (x,y) in tmp_geom] # lets make 4x4 width = (parts_bounding_box[2] - parts_bounding_box[0])*self.sc + self.x_gap height = (parts_bounding_box[3] - parts_bounding_box[1])*self.sc + self.y_gap # check if will all fit in one window, if not fill first and check if remainder will fit in second window max_num_cols = divmod(self.sketch_bounding_box[2] - self.sketch_bounding_box[0], width)[0] max_num_rows = divmod(self.sketch_bounding_box[3] - self.sketch_bounding_box[1], height)[0] if max_num_cols == 0 or max_num_rows == 0: print('Cannot tile into this area') design.remove_operation(new_web) return Laminate() # check if can fit in one # if N <= max_num_rows*max_num_cols: rows = math.ceil(self.N / max_num_cols) cols = math.ceil(self.N / rows) # spread across the two windows upper_right_origin_bounding_box = (self.sketch_bounding_box[0], self.sketch_bounding_box[3]) n_count = 0 arrayed_reference_lines = [] for row in range(rows): for col in range(cols): if n_count >= self.N or n_count >= max_num_rows*max_num_cols*2: break newx = upper_right_origin_bounding_box[0] + locate_lines[0][0] + col*width newy = upper_right_origin_bounding_box[1] - locate_lines[1][1] - row*height arrayed_reference_lines.append([(newx, newy), (newx, newy + height)]) n_count = n_count + 1 construction_geom_sheet = Sketch.new() construction_line = [GenericLine.gen_from_point_lists(line,[],construction=False) for line in arrayed_reference_lines] construction_geom_sheet.addoperationgeometries(construction_line) # add sketch to sketch list design_copy.sketches[construction_geom_sheet.id] = construction_geom_sheet ######################## External transform the hinge onto the sheet construction line # # insert hinge into sheet as subdesign # sheet.subdesigns[hinge.id] = hinge # # make design links operation_links = {} operation_links['from'] = [(part_to_insert.id,0)] sketch_links = {} sketch_links['sketch_to'] = [construction_geom_sheet.id] sketch_links['sketch_from'] = [construction_geom_hinge.id] insert_part = TransformInternal(sketch_links, operation_links, 'scale', 'scale', 0, False, 1., 1.) insert_part.customname = 'Inserted part' design_copy.addoperation(insert_part) insert_part.generate(design_copy) insert_part_id = design_copy.operations[-1].id # save for later ######################## External transform the web.sheet to the construction line # # make design links operation_links = {} operation_links['from'] = [(new_web.id,1)] sketch_links = {} sketch_links['sketch_to'] = [construction_geom_sheet.id] sketch_links['sketch_from'] = [construction_geom_hinge.id] insert_webs = TransformInternal(sketch_links, operation_links, 'scale', 'scale', 0, False, 1., 1.) insert_webs.customname = 'Inserted part webs' design_copy.addoperation(insert_webs) insert_webs.generate(design_copy) ######################## Remove web.sheet from sheet, union external transform + generateed sheet with hole + web # first the difference # link 1 is the sheet sheet_with_hole = LaminateOperation2({'unary': [(sheet_to_insert_into.id,0)], 'binary': [(insert_webs.id,0)]},'difference') sheet_with_hole.customname = 'Sheet with hole' design_copy.addoperation(sheet_with_hole) sheet_with_hole.generate(design_copy) sheet_with_part = LaminateOperation2({'unary': [(sheet_with_hole.id,0), (insert_part_id,0)], 'binary':[]},'union') sheet_with_part.customname = 'First pass cuts' design_copy.addoperation(sheet_with_part) sheet_with_part.generate(design_copy) # ######################## Make release cut laminate operation operation_links = {} operation_links['from'] = [(release_to_insert_into.id,0)] sketch_links = {} sketch_links['sketch_to'] = [construction_geom_sheet.id] sketch_links['sketch_from'] = [construction_geom_hinge.id] insert_release = TransformInternal(sketch_links, operation_links, 'scale', 'scale', 0, False, 1., 1.) design.addoperation(insert_release) insert_release.generate(design) ######################################### prepare outputs # delete the intermediate layers design.remove_operation(sheet_with_hole) design.remove_operation(insert_webs) design.remove_operation(insert_part) design.remove_operation(new_web) design.remove_operation(sheet_with_part) design.remove_operation(insert_release) self.output = [OperationOutput(sheet_with_part.output[0].csg, 'FirstCuts', self), OperationOutput(sheet_with_part.output[0].csg, 'FirstCuts', self), OperationOutput(insert_release.output[0].csg, 'Release', self)] return sheet_with_part.output[0].csg
def generate(self, design): result = self.operate(design) output = OperationOutput(result, 'default', self) self.output = [output]
def generate(self, design): safe_buffer1 = .5 *popupcad.csg_processing_scaling safe_buffer2 = .5 *popupcad.csg_processing_scaling safe_buffer3 = .5 *popupcad.csg_processing_scaling parent_id, parent_output_index = self.operation_links['parent'][0] parent_index = design.operation_index(parent_id) parent = design.operations[parent_index].output[ parent_output_index].csg fixed_id, fixed_output_index = self.operation_links['fixed'][0] fixed_index = design.operation_index(fixed_id) fixed = design.operations[fixed_index].output[fixed_output_index].csg layerdef = design.return_layer_definition() allgeoms = [] allhingelines = [] buffered_splits = [] all_joint_props = {} for joint_def in self.joint_defs: allgeoms4, buffered_split, hingelines, joint_props = self.gen_geoms( joint_def, layerdef, design) allgeoms.extend(allgeoms4) allhingelines.extend(hingelines) buffered_splits.append(buffered_split) for jointline,jointprop in zip(hingelines,joint_props): all_joint_props[jointline]=jointprop #allhingelines, buffered_splits = zip(*sorted(zip(allhingelines, allgeoms, buffered_splits))) #allhingelines = list(allhingelines) #allgeoms = list(allgeoms) #buffered_splits = list(buffered_splits) safe_sections = [] if len(allgeoms)>1: for ii in range(len(allgeoms)): unsafe = Laminate.unaryoperation(allgeoms[:ii] +allgeoms[ii + 1:],'union') unsafe_buffer = unsafe.buffer(safe_buffer1,resolution=self.resolution) safe_sections.append(allgeoms[ii].difference(unsafe_buffer)) safe = Laminate.unaryoperation(safe_sections, 'union') else: safe_sections.append(allgeoms[0]) safe = allgeoms[0] buffered_splits2 = Laminate.unaryoperation(buffered_splits, 'union') safe_buffer = safe.buffer(safe_buffer2, resolution=self.resolution) unsafe = Laminate.unaryoperation( allgeoms, 'union').difference(safe_buffer) unsafe2 = unsafe.buffer(safe_buffer3, resolution=self.resolution) split1 = parent.difference(unsafe2) split2 = split1.difference(buffered_splits2) bodies = popupcad.algorithms.body_detection.find( split2.to_generic_laminate()) bodies_generic = [item.to_generic_laminate() for item in bodies] connections = {} connections2 = {} for line, geom in zip(allhingelines, safe_sections): connections[line] = [] connections2[line] = [] for body, body_generic in zip(bodies, bodies_generic): if not geom.intersection(body).isEmpty(): connections[line].append(body_generic) connections2[line].append(body) for line, geoms in connections2.items(): connections2[line] = Laminate.unaryoperation(geoms, 'union') self.fixed_bodies = [] fixed_csg = [] for body, body_generic in zip(bodies, bodies_generic): if not fixed.intersection(body).isEmpty(): self.fixed_bodies.append(body_generic) fixed_csg.append(body) self.bodies_generic = bodies_generic allhingelines.sort() #Sort here to prevent interfering with geometry. We only care about order of the joint props self.connections = sorted([(key, connections[key]) for key in allhingelines if len(connections[key]) == 2]) self.all_joint_props = [all_joint_props[key] for key in allhingelines if len(connections[key]) == 2] self.output = [] self.output.append(OperationOutput(safe,'Safe',self)) self.output.append(OperationOutput(unsafe,'Unsafe',self)) self.output.append(OperationOutput(split1,'Split1',self)) self.output.append(OperationOutput(split2,'Split2',self)) #TODO Change output to match the names that get exported to Gazebo self.output.extend([OperationOutput(item,'Fixed {0:d}'.format(ii),self) for ii,item in enumerate(fixed_csg)]) self.output.extend([OperationOutput(item,'Body {0:d}'.format(ii),self) for ii,item in enumerate(bodies)]) self.output.extend([OperationOutput(item,'Connection {0:d}'.format(ii),self) for ii,item in enumerate(connections2.values())]) self.output.insert(0, self.output[3])
def operate(self, design): """ Return a generic_laminate ref of a layup laminate with all the layers of the part and with the appropriate 25x25mm alignment features compatible with the Wood lab micro-robotics manufacturing process. Input: Design -> a popupcad design file Output: layup -> A handle to the layup design file subop -> A subop which is inserted into the input design file to reduce the number of operations """ #### general geometry constants that most layups will have sheet_width = self.values[0] # mm hole_offset = self.values[1] # location of hole in from corner hole_rad = self.values[2] # alignment pin geoms cross_len = .75 # tick length cross_horiz = sheet_width / 2 - 2 * cross_len # horizontal dimension from center crosshair dt = 0.001 # small thickness for crosshair buff_x = 5 # for window sizes buff_y = 1 wind_h = 1 space_x = 1.3 # window width, maximum of 1 mm wind_w = lambda N: max( min((sheet_width - 2 * buff_x) / (N + 1.3 * N - 1.3), 1), 0.01) # the laminate design layup = design # popupcad.filetypes.design.Design.new() layer_list = design.return_layer_definition().layers # initiate the sketches ############# sheet first sheet = Sketch.new() tmp_geom = [(-sheet_width / 2., -sheet_width / 2.), (-sheet_width / 2., sheet_width / 2.), (sheet_width / 2., sheet_width / 2.), (sheet_width / 2., -sheet_width / 2.)] sheet_poly = popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists( tmp_geom, []) sheet.addoperationgeometries([sheet_poly]) ############# holes second holes = Sketch.new() tmp_geom = [ (-sheet_width / 2. + hole_offset, -sheet_width / 2. + hole_offset), (-sheet_width / 2. + hole_offset, sheet_width / 2. - hole_offset), (sheet_width / 2. - hole_offset, sheet_width / 2. - hole_offset), (sheet_width / 2. - hole_offset, -sheet_width / 2. + hole_offset) ] # make list of hole geometry holes_poly = [ popupcad.filetypes.genericshapes.GenericCircle. gen_from_point_lists([pt, (pt[0] + hole_rad, pt[1])], []) for pt in tmp_geom ] holes.addoperationgeometries(holes_poly) ############# upper triangle left_tri = Sketch.new() tmp_geom = [ (-sheet_width / 2. + hole_offset / 4, sheet_width / 2. - hole_offset * (2 / 3)), (-sheet_width / 2. + hole_offset / 4 + hole_rad, sheet_width / 2. - hole_offset * (2 / 3)), (-sheet_width / 2. + hole_offset / 4 + 0.5 * hole_rad, sheet_width / 2. - hole_offset * (2 / 3) + 1.2 * hole_rad * .75) ] # make list of hole geometry sheet_poly = popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists( tmp_geom, []) left_tri.addoperationgeometries([sheet_poly]) ############# crosshairs cross_hairs = Sketch.new() tmp_geom_horiz = [(0, -cross_len), (0, cross_len)] tmp_geom_vert = [(-cross_len, 0), (cross_len, 0)] shift = [-cross_horiz, 0, cross_horiz] cross_poly_horiz = [ popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists( [(tmp_geom_horiz[0][0] + c - dt / 2., tmp_geom_horiz[0][1] - dt / 2.), (tmp_geom_horiz[1][0] + c - dt / 2., tmp_geom_horiz[1][1] - dt / 2.), (tmp_geom_horiz[1][0] + c + dt / 2., tmp_geom_horiz[1][1] + dt / 2.), (tmp_geom_horiz[0][0] + c + dt / 2., tmp_geom_horiz[0][1] - dt / 2.)], []) for c in shift ] cross_poly_vert = [ popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists( [(tmp_geom_vert[0][0] + c - dt / 2., tmp_geom_vert[0][1] - dt / 2.), (tmp_geom_vert[1][0] + c - dt / 2., tmp_geom_vert[1][1] + dt / 2.), (tmp_geom_vert[1][0] + c + dt / 2., tmp_geom_vert[1][1] + dt / 2.), (tmp_geom_vert[0][0] + c + dt / 2., tmp_geom_vert[0][1] - dt / 2.)], []) for c in shift ] cross_hairs.addoperationgeometries(cross_poly_horiz + cross_poly_vert) # Build the sheet with holes # Add the sketches to the sketch list layup.sketches[sheet.id] = sheet layup.sketches[holes.id] = holes layup.sketches[cross_hairs.id] = cross_hairs layup.sketches[left_tri.id] = left_tri # get the layer links for making sketch ops layer_links = [layer.id for layer in layer_list] holes_sketch = popupcad.manufacturing.simplesketchoperation.SimpleSketchOp( {'sketch': [holes.id]}, layer_links) holes_sketch.name = "Holes" trian_sketch = popupcad.manufacturing.simplesketchoperation.SimpleSketchOp( {'sketch': [left_tri.id]}, layer_links) trian_sketch.name = "Left triangle" sheet_sketch = popupcad.manufacturing.simplesketchoperation.SimpleSketchOp( {'sketch': [sheet.id]}, layer_links) sheet_sketch.name = "sheet" cross_sketch = popupcad.manufacturing.simplesketchoperation.SimpleSketchOp( {'sketch': [cross_hairs.id]}, layer_links) cross_sketch.name = "Crosshairs" # laminate operation to combine cross hairs and holes sheet_with_holes = popupcad.manufacturing.laminateoperation2.LaminateOperation2( { 'unary': [(sheet_sketch.id, 0)], 'binary': [(holes_sketch.id, 0), (cross_sketch.id, 0), (trian_sketch.id, 0)] }, 'difference') sheet_with_holes.name = "Sheet with holes" ############# rectangle windows windows = [Sketch.new() for _ in layer_list] windows_sketchop = [] # make windows, center on middle of sheet at bottom window_width = wind_w(len(windows)) window_coords = np.array([ round(kk * (1 + space_x) * window_width, 4) for kk in range(len(windows)) ]) window_coords = list(window_coords - np.mean(window_coords)) # center is 0 for kk, (layer, window, x_coord) in enumerate(zip(layer_list, windows, window_coords)): window.name = layer.name + '_window' tmp_geom = [(x_coord, -sheet_width / 2. + buff_y), (x_coord, -sheet_width / 2. + buff_y + wind_h), (x_coord + window_width, -sheet_width / 2. + buff_y + wind_h), (x_coord + window_width, -sheet_width / 2. + buff_y)] sheet_poly = popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists( tmp_geom, []) window.addoperationgeometries([sheet_poly]) layup.sketches[window.id] = window # make a sketch op on all layers above the current layer, this will be removed with a difference from the sheet windows_sketchop.append( popupcad.manufacturing.simplesketchoperation.SimpleSketchOp( {'sketch': [window.id]}, layer_links[kk + 1:])) windows_sketchop[-1].name = "Window_" + layer.name # laminate operation to remove windows from sheet with holes sheet_with_windows = popupcad.manufacturing.laminateoperation2.LaminateOperation2( { 'unary': [(sheet_with_holes.id, 0)], 'binary': [(sktch.id, 0) for sktch in windows_sketchop] }, 'difference') sheet_with_windows.name = "Final sheet" # add the sketch ops to the design and generate the sketch op other_ops = windows_sketchop + [ trian_sketch, holes_sketch, sheet_sketch, cross_sketch, sheet_with_holes, sheet_with_windows ] [layup.addoperation(item) for item in other_ops] [item.generate(layup) for item in other_ops] [layup.remove_operation(item) for item in other_ops] self.output = [ OperationOutput(sheet_with_windows.output[0], "OutputLaminate", self) ] return sheet_with_windows.output[0].csg