예제 #1
0
 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])
예제 #2
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]
예제 #3
0
 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])
예제 #4
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]
예제 #5
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)

        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]
예제 #6
0
    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
예제 #7
0
 def generate(self, design):
     result = self.operate(design)
     output = OperationOutput(result, 'default', self)
     self.output = [output]
예제 #8
0
    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