예제 #1
0
    def _slicer_task_4b(layer, ewidth, iwidth, conf, top_masks, bot_masks,
                        perims):
        # Solid Mask
        outmask = []
        for mask in top_masks:
            outmask = geom.union(outmask, geom.close_paths(mask))
        for mask in bot_masks:
            outmask = geom.union(outmask, geom.close_paths(mask))
        solid_mask = geom.clip(outmask, perims[-1])
        bounds = geom.paths_bounds(outmask)

        # Solid Infill
        solid_infill = []
        base_ang = 45 if layer % 2 == 0 else -45
        solid_mask = geom.offset(solid_mask, conf['infill_overlap'] - ewidth)
        lines = geom.make_infill_lines(bounds, base_ang, 1.0, ewidth)
        for line in lines:
            lines = [line]
            lines = geom.clip(lines, solid_mask, subj_closed=False)
            solid_infill.extend(lines)

        # Sparse Infill
        sparse_infill = []
        infill_type = conf['infill_type']
        density = conf['infill_density'] / 100.0
        if density > 0.0:
            if density >= 0.99:
                infill_type = "Lines"
            mask = geom.offset(perims[-1], conf['infill_overlap'] - iwidth)
            mask = geom.diff(mask, solid_mask)
            if infill_type == "Lines":
                base_ang = 90 * (layer % 2) + 45
                lines = geom.make_infill_lines(bounds, base_ang, density,
                                               iwidth)
            elif infill_type == "Triangles":
                base_ang = 60 * (layer % 3)
                lines = geom.make_infill_triangles(bounds, base_ang, density,
                                                   iwidth)
            elif infill_type == "Grid":
                base_ang = 90 * (layer % 2) + 45
                lines = geom.make_infill_grid(bounds, base_ang, density,
                                              iwidth)
            elif infill_type == "Hexagons":
                base_ang = 120 * (layer % 3)
                lines = geom.make_infill_hexagons(bounds, base_ang, density,
                                                  iwidth)
            else:
                lines = []
            for line in lines:
                lines = [line]
                lines = geom.clip(lines, mask, subj_closed=False)
                sparse_infill.extend(lines)
        return solid_infill, sparse_infill
예제 #2
0
    def _slicer_task_4a(ewidth, conf, layer_paths, supp_outline):
        # Raft
        raft_outline = []
        raft_infill = []
        if conf['adhesion_type'] == "Raft":
            rings = math.ceil(conf['brim_width'] / ewidth)
            outset = min(conf['skirt_outset'] + ewidth * conf['skirt_loops'],
                         conf['raft_outset'])
            paths = geom.union(layer_paths, supp_outline)
            raft_outline = geom.offset(paths, outset)
            bounds = geom.paths_bounds(raft_outline)
            mask = geom.offset(raft_outline, conf['infill_overlap'] - ewidth)
            lines = geom.make_infill_lines(bounds, 0, 0.75, ewidth)
            raft_infill.append(geom.clip(lines, mask, subj_closed=False))
            for layer in range(conf['raft_layers'] - 1):
                base_ang = 90 * ((layer + 1) % 2)
                lines = geom.make_infill_lines(bounds, base_ang, 1.0, ewidth)
                raft_infill.append(
                    geom.clip(lines, raft_outline, subj_closed=False))

        # Brim
        brim = []
        adhesion = conf['adhesion_type']
        brim_w = conf['brim_width']
        if adhesion == "Brim":
            rings = math.ceil(brim_w / ewidth)
            for i in range(rings):
                brim.append(geom.offset(layer_paths, (i + 0.5) * ewidth))

        # Skirt
        skirt = []
        priming = []
        skirt_w = conf['skirt_outset']
        minloops = conf['skirt_loops']
        minlen = conf['skirt_min_len']
        skirt = geom.offset(layer_paths, brim_w + skirt_w + ewidth / 2.0)
        plen = sum(
            sum([
                math.hypot(p2[0] - p1[0], p2[1] - p1[1])
                for p1, p2 in zip(path, path[1:] + path[0:1])
            ]) for path in skirt)
        loops = minloops
        if adhesion != "Raft":
            loops = max(loops, math.ceil(minlen / plen))
        for i in range(loops - 1):
            priming.append(geom.offset(skirt, (i + 1) * ewidth))

        return (geom.close_paths(raft_outline), raft_infill,
                geom.close_paths(brim), geom.close_paths(skirt),
                geom.close_paths(priming))
예제 #3
0
 def _slicer_task_3b(layer, conf, ewidth, overhangs):
     # Support
     outline = []
     infill = []
     density = conf['support_density'] / 100.0
     if density > 0.0:
         outline = geom.offset(overhangs, -ewidth / 2.0)
         outline = geom.close_paths(outline)
         mask = geom.offset(outline, conf['infill_overlap'] - ewidth)
         bounds = geom.paths_bounds(mask)
         lines = geom.make_infill_lines(bounds, 0, density, ewidth)
         infill = geom.clip(lines, mask, subj_closed=False)
     return outline, infill
예제 #4
0
    def _slicer_task_1(z, ewidth, suppwidth, layer_h, conf, model):
        # Layer Slicing
        paths = model.slice_at_z(z - layer_h / 2, layer_h)
        paths = geom.orient_paths(paths)
        paths = geom.union(paths, [])

        # Overhang Masks
        supp_ang = conf['overhang_angle']
        tris = model.get_overhang_footprint_triangles(ang=supp_ang, z=z)
        overhangs = geom.diff(geom.union(tris, []), paths)

        # Perimeters
        perims = []
        for i in range(conf['shell_count']):
            shell = geom.offset(paths, -(i + 0.5) * ewidth)
            shell = geom.close_paths(shell)
            perims.append(shell)

        return paths, overhangs, perims
예제 #5
0
    def slice_to_file(self, filename, showgui=False, threads=-1):
        print("Slicing start")
        layer_h = self.conf['layer_height']
        dflt_nozl = self.conf['default_nozzle']
        infl_nozl = self.conf['infill_nozzle']
        supp_nozl = self.conf['support_nozzle']
        ptcache = self.model.points
        if infl_nozl == -1:
            infl_nozl = dflt_nozl
        if supp_nozl == -1:
            supp_nozl = dflt_nozl
        dflt_nozl_d = self.conf['nozzle_{0}_diam'.format(dflt_nozl)]
        infl_nozl_d = self.conf['nozzle_{0}_diam'.format(infl_nozl)]
        supp_nozl_d = self.conf['nozzle_{0}_diam'.format(supp_nozl)]
        self.layer_height = layer_h
        self.extrusion_ratio = 1.25
        self.extrusion_width = dflt_nozl_d * self.extrusion_ratio
        self.infill_width = infl_nozl_d * self.extrusion_ratio
        self.support_width = supp_nozl_d * self.extrusion_ratio
        height = self.model.points.maxz - self.model.points.minz
        layer_cnt = math.floor(height / layer_h)
        self.model.assign_layers(layer_h)
        self.layer_zs = [
            self.model.points.minz + layer_h * (layer + 1)
            for layer in range(layer_cnt)
        ]
        if threads <= 0:
            threads = multiprocessing.cpu_count() * 2

        # print('<tkcad formatversion="1.1" units="inches" showfractions="YES" material="Aluminum">', file=sys.stderr)
        executor = ThreadPoolExecutor if threads == 1 else ProcessPoolExecutor
        with executor(max_workers=threads) as ex:
            print("Stage 1: Perimeters")
            (self.layer_paths, self.overhang_masks,
             self.perimeter_paths) = zip(*list(
                 ex.map(Slicer._slicer_task_1,
                        self.layer_zs, [self.extrusion_width] *
                        layer_cnt, [self.support_width] *
                        layer_cnt, [layer_h] * layer_cnt, [self.conf] *
                        layer_cnt, [self.model] * layer_cnt,
                        chunksize=20)))

            print("Stage 2: Generate Masks")
            overhang_future = ex.submit(Slicer._slicer_task_2a, self.conf,
                                        self.overhang_masks, self.layer_paths)

            top_masks, bot_masks = zip(*list(
                ex.map(Slicer._slicer_task_2b,
                       range(layer_cnt), [(
                           [] if i < 1 else self.perimeter_paths[i - 1][-1])
                                          for i in range(layer_cnt)],
                       [p[-1] for p in self.perimeter_paths],
                       [([] if i >= layer_cnt -
                         1 else self.perimeter_paths[i + 1][-1])
                        for i in range(layer_cnt)],
                       chunksize=20)))

            overhang_drops = overhang_future.result()

            print("Stage 3: Support & Raft")
            (self.support_outline, self.support_infill) = zip(*list(
                ex.map(Slicer._slicer_task_3b,
                       range(layer_cnt), [self.conf] *
                       layer_cnt, [self.support_width] * layer_cnt,
                       overhang_drops,
                       chunksize=20)))
            del overhang_drops

            print("Stage 4: Path Generation")
            self.future_raft = ex.submit(self._slicer_task_4a,
                                         self.support_width, self.conf,
                                         self.layer_paths[0],
                                         self.support_outline[0])

            top_cnt = self.conf['top_layers']
            bot_cnt = self.conf['bottom_layers']
            (self.solid_infill, self.sparse_infill) = zip(*list(
                ex.map(self._slicer_task_4b,
                       range(layer_cnt), [self.extrusion_width] *
                       layer_cnt, [self.infill_width] *
                       layer_cnt, [self.conf] * layer_cnt,
                       [top_masks[i:i + top_cnt] for i in range(layer_cnt)], [
                           bot_masks[max(0, i - bot_cnt + 1):i + 1]
                           for i in range(layer_cnt)
                       ],
                       self.perimeter_paths,
                       chunksize=20)))

            (self.raft_outline, self.raft_infill, self.brim_paths,
             self.skirt_paths, self.priming_paths) = self.future_raft.result()

            del top_masks
            del bot_masks

        raft_layers = len(self.raft_infill)
        for i in range(raft_layers):
            self.layer_zs.append(self.layer_zs[-1] + self.conf['layer_height'])

        print("Gcode")
        with open(filename, "w") as f:
            f.write("( raft_outline )\n")
            outline = geom.close_paths(self.raft_outline)
            for line in self._paths_gcode(outline, self.support_width,
                                          supp_nozl, self.layer_zs[0]):
                f.write(line)
            f.write("( raft_infill )\n")
            for layer, layer_paths in enumerate(self.raft_infill):
                for line in self._paths_gcode(layer_paths, self.support_width,
                                              supp_nozl, self.layer_zs[layer]):
                    f.write(line)

            layer = raft_layers
            if self.priming_paths:
                f.write("( priming )\n")
                paths = geom.close_paths(self.priming_paths)
                for line in self._paths_gcode(paths, self.support_width,
                                              supp_nozl, self.layer_zs[layer]):
                    f.write(line)

            if self.skirt_paths:
                f.write("( skirt )\n")
                for line in self._paths_gcode(self.skirt_paths,
                                              self.support_width, supp_nozl,
                                              self.layer_zs[layer]):
                    f.write(line)

            if self.brim_paths:
                f.write("( brim )\n")
                paths = self.brim_paths
                for line in self._paths_gcode(paths + paths[0],
                                              self.support_width, supp_nozl,
                                              self.layer_zs[layer]):
                    f.write(line)

            for slicenum in range(len(self.perimeter_paths)):
                layer = raft_layers + slicenum
                outline = geom.close_paths(self.support_outline[slicenum])
                f.write("( support outline )\n")
                for line in self._paths_gcode(outline, self.support_width,
                                              supp_nozl, self.layer_zs[layer]):
                    f.write(line)
                f.write("( support infill )\n")
                for line in self._paths_gcode(self.support_infill[slicenum],
                                              self.support_width, supp_nozl,
                                              self.layer_zs[layer]):
                    f.write(line)

                f.write("( perimeters )\n")
                for paths in reversed(self.perimeter_paths[slicenum]):
                    paths = geom.close_paths(paths)
                    for line in self._paths_gcode(paths, self.extrusion_width,
                                                  dflt_nozl,
                                                  self.layer_zs[layer]):
                        f.write(line)
                f.write("( solid fill )\n")
                for line in self._paths_gcode(self.solid_infill[slicenum],
                                              self.extrusion_width, dflt_nozl,
                                              self.layer_zs[layer]):
                    f.write(line)

                f.write("( sparse infill )\n")
                for line in self._paths_gcode(self.sparse_infill[slicenum],
                                              self.infill_width, infl_nozl,
                                              self.layer_zs[layer]):
                    f.write(line)

        # print('</tkcad>', file=sys.stderr)
        if showgui:
            self._display_paths()