⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image-to-gcode.py

📁 CNC 的开放码,EMC2 V2.2.8版
💻 PY
📖 第 1 页 / 共 2 页
字号:
#!/usr/bin/python## image-to-gcode is free software; you can redistribute it and/or modify## it under the terms of the GNU General Public License as published by the## Free Software Foundation; either version 2 of the License, or (at your## option) any later version.  image-to-gcode is distributed in the hope ## that it will be useful, but WITHOUT ANY WARRANTY; without even the implied## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See## the GNU General Public License for more details.  You should have## received a copy of the GNU General Public License along with image-to-gcode;## if not, write to the Free Software Foundation, Inc., 59 Temple Place,## Suite 330, Boston, MA 02111-1307 USA## ## image-to-gcode.py is Copyright (C) 2005 Chris Radek## chris@timeguy.com## image-to-gcode.py is Copyright (C) 2006 Jeff Epler## jepler@unpy.netimport sys, osBASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))sys.path.insert(0, os.path.join(BASE, "lib", "python"))import gettext;gettext.install("axis", localedir=os.path.join(BASE, "share", "locale"), unicode=True)import Image, numarrayimport numarray.ieeespecial as ieeefrom rs274.author import Gcodeimport rs274.optionsfrom math import *import operatorepsilon = 1e-5def ball_tool(r,rad):    s = -sqrt(rad**2-r**2)    return sdef endmill(r,dia):    return 0def vee_common(angle):    slope = tan(angle * pi / 180)    def f(r, dia):        return r * slope    return ftool_makers = [ ball_tool, endmill, vee_common(45), vee_common(60)]def make_tool_shape(f, wdia, resp):    res = 1. / resp    dia = int(wdia*res+.5)    wrad = wdia/2.    if dia < 2: dia = 2    n = numarray.array([[ieee.plus_inf] * dia] * dia, type="Float32")    hdia = dia / 2.    l = []    for x in range(dia):        for y in range(dia):            r = hypot(x-hdia, y-hdia) * resp            if r < wrad:                z = f(r, wrad)                l.append(z)                n[x,y] = z    n = n - n.min()    return ndef amax(seq):    res = 0    for i in seq:        if abs(i) > abs(res): res = i    return resdef group_by_sign(seq, slop=sin(pi/18), key=lambda x:x):    sign = None    subseq = []    for i in seq:        ki = key(i)        if sign is None:            subseq.append(i)            if ki != 0:                sign = ki / abs(ki)        else:            subseq.append(i)            if sign * ki < -slop:                sign = ki / abs(ki)                yield subseq                subseq = [i]    if subseq: yield subseqclass Convert_Scan_Alternating:    def __init__(self):        self.st = 0    def __call__(self, primary, items):        st = self.st = self.st + 1        if st % 2: items.reverse()        if st == 1: yield True, items        else: yield False, items    def reset(self):        self.st = 0class Convert_Scan_Increasing:    def __call__(self, primary, items):        yield True, items    def reset(self):        passclass Convert_Scan_Decreasing:    def __call__(self, primary, items):        items.reverse()        yield True, items    def reset(self):        passclass Convert_Scan_Upmill:    def __init__(self, slop = sin(pi / 18)):        self.slop = slop    def __call__(self, primary, items):        for span in group_by_sign(items, self.slop, operator.itemgetter(2)):            if amax([it[2] for it in span]) < 0:                span.reverse()            yield True, span    def reset(self):        passclass Convert_Scan_Downmill:    def __init__(self, slop = sin(pi / 18)):        self.slop = slop    def __call__(self, primary, items):        for span in group_by_sign(items, self.slop, operator.itemgetter(2)):            if amax([it[2] for it in span]) > 0:                span.reverse()            yield True, span    def reset(self):        passclass Reduce_Scan_Lace:    def __init__(self, converter, slope, keep):        self.converter = converter        self.slope = slope        self.keep = keep    def __call__(self, primary, items):        slope = self.slope        keep = self.keep        if primary:            idx = 3            test = operator.le        else:            idx = 2            test = operator.ge        def bos(j):            return j - j % keep        def eos(j):            if j % keep == 0: return j            return j + keep - j%keep        for i, (flag, span) in enumerate(self.converter(primary, items)):            subspan = []            a = None            for i, si in enumerate(span):                ki = si[idx]                if a is None:                    if test(abs(ki), slope):                        a = b = i                else:                    if test(abs(ki), slope):                        b = i                    else:                        if i - b < keep: continue                        yield True, span[bos(a):eos(b+1)]                        a = None            if a is not None:                yield True, span[a:]    def reset(self):        self.primary.reset()unitcodes = ['G20', 'G21']convert_makers = [ Convert_Scan_Increasing, Convert_Scan_Decreasing, Convert_Scan_Alternating, Convert_Scan_Upmill, Convert_Scan_Downmill ]def progress(a, b):    if os.environ.has_key("AXIS_PROGRESS_BAR"):        print >>sys.stderr, "FILTER_PROGRESS=%d" % int(a*100./b+.5)        sys.stderr.flush()class Converter:    def __init__(self,            image, units, tool_shape, pixelsize, pixelstep, safetyheight, \            tolerance, feed, convert_rows, convert_cols, cols_first_flag,            entry_cut, spindle_speed, roughing_offset, roughing_delta,            roughing_feed):        self.image = image        self.units = units        self.tool = tool_shape        self.pixelsize = pixelsize        self.pixelstep = pixelstep        self.safetyheight = safetyheight        self.tolerance = tolerance        self.base_feed = feed        self.convert_rows = convert_rows        self.convert_cols = convert_cols        self.cols_first_flag = cols_first_flag        self.entry_cut = entry_cut        self.spindle_speed = spindle_speed        self.roughing_offset = roughing_offset        self.roughing_delta = roughing_delta        self.roughing_feed = roughing_feed        self.cache = {}        w, h = self.w, self.h = image.shape        ts = self.ts = tool_shape.shape[0]        self.h1 = h - ts        self.w1 = w - ts        self.tool_shape = tool_shape * self.pixelsize * ts / 2;        def one_pass(self):        g = self.g        g.set_feed(self.feed)        if self.convert_cols and self.cols_first_flag:            self.g.set_plane(19)            self.mill_cols(self.convert_cols, True)            if self.convert_rows: g.safety()        if self.convert_rows:            self.g.set_plane(18)            self.mill_rows(self.convert_rows, not self.cols_first_flag)        if self.convert_cols and not self.cols_first_flag:            self.g.set_plane(19)            if self.convert_rows: g.safety()            self.mill_cols(self.convert_cols, not self.convert_rows)        if self.convert_cols:            self.convert_cols.reset()        if self.convert_rows:            self.convert_rows.reset()        g.safety()    def convert(self):        self.g = g = Gcode(safetyheight=self.safetyheight,                           tolerance=self.tolerance,                           spindle_speed=self.spindle_speed,                           units=self.units)        g.begin()        g.continuous(self.tolerance)        g.safety()        if self.roughing_delta and self.roughing_offset:            base_image = self.image            rough = make_tool_shape(ball_tool,                                2*self.roughing_offset, self.pixelsize)            w, h = base_image.shape            tw, th = rough.shape            w1 = w + tw            h1 = h + th            nim1 = numarray.zeros((w1, h1), 'Float32') + base_image.min()            nim1[tw/2:tw/2+w, th/2:th/2+h] = base_image            self.image = numarray.zeros((w,h), type="Float32")            for j in range(0, w):                progress(j,w)                for i in range(0, h):                    self.image[j,i] = (nim1[j:j+tw,i:i+th] - rough).max()            self.feed = self.roughing_feed            r = -self.roughing_delta            m = self.image.min()            self.ro = self.roughing_offset            while r > m:                self.rd = r                self.one_pass()                r = r - self.roughing_delta            if r < m + epsilon:                self.rd = m                self.one_pass()            self.image = base_image            self.cache.clear()        self.feed = self.base_feed        self.ro = 0        self.rd = self.image.min()        self.one_pass()        g.end()    def get_z(self, x, y):        try:            return min(0, max(self.rd, self.cache[x,y]) + self.ro)        except KeyError:            m1 = self.image[y:y+self.ts, x:x+self.ts]            self.cache[x,y] = d = (m1 - self.tool).max()            return min(0, max(self.rd, d) + self.ro)            def get_dz_dy(self, x, y):        y1 = max(0, y-1)        y2 = min(self.image.shape[0]-1, y+1)        dy = self.pixelsize * (y2-y1)        return (self.get_z(x, y2) - self.get_z(x, y1)) / dy            def get_dz_dx(self, x, y):        x1 = max(0, x-1)        x2 = min(self.image.shape[1]-1, x+1)        dx = self.pixelsize * (x2-x1)        return (self.get_z(x2, y) - self.get_z(x1, y)) / dx    def mill_rows(self, convert_scan, primary):        w1 = self.w1; h1 = self.h1;        pixelsize = self.pixelsize; pixelstep = self.pixelstep        jrange = range(0, w1, pixelstep)        if w1-1 not in jrange: jrange.append(w1-1)        irange = range(h1)        for j in jrange:            progress(jrange.index(j), len(jrange))            y = (w1-j) * pixelsize            scan = []            for i in irange:                x = i * pixelsize                milldata = (i, (x, y, self.get_z(i, j)),                    self.get_dz_dx(i, j), self.get_dz_dy(i, j))                scan.append(milldata)            for flag, points in convert_scan(primary, scan):                if flag:                    self.entry_cut(self, points[0][0], j, points)                for p in points:                    self.g.cut(*p[1])            self.g.flush()    def mill_cols(self, convert_scan, primary):        w1 = self.w1; h1 = self.h1;        pixelsize = self.pixelsize; pixelstep = self.pixelstep        jrange = range(0, h1, pixelstep)        irange = range(w1)        if h1-1 not in jrange: jrange.append(h1-1)        jrange.reverse()        for j in jrange:            progress(jrange.index(j), len(jrange))            x = j * pixelsize            scan = []            for i in irange:                y = (w1-i) * pixelsize                milldata = (i, (x, y, self.get_z(j, i)),                    self.get_dz_dy(j, i), self.get_dz_dx(j, i))                scan.append(milldata)            for flag, points in convert_scan(primary, scan):                if flag:                    self.entry_cut(self, j, points[0][0], points)                for p in points:                    self.g.cut(*p[1])            self.g.flush()def convert(*args, **kw):    return Converter(*args, **kw).convert()class SimpleEntryCut:    def __init__(self, feed):        self.feed = feed    def __call__(self, conv, i0, j0, points):        p = points[0][1]        if self.feed:            conv.g.set_feed(self.feed)        conv.g.safety()        conv.g.rapid(p[0], p[1])        if self.feed:            conv.g.set_feed(conv.feed)def circ(r,b):     """\Calculate the portion of the arc to do so that none is above thesafety height (that's just silly)"""    z = r**2 - (r-b)**2    if z < 0: z = 0    return z**.5class ArcEntryCut:    def __init__(self, feed, max_radius):        self.feed = feed        self.max_radius = max_radius    def __call__(self, conv, i0, j0, points):        if len(points) < 2:            p = points[0][1]            if self.feed:                conv.g.set_feed(self.feed)            conv.g.safety()            conv.g.rapid(p[0], p[1])            if self.feed:                conv.g.set_feed(conv.feed)            return        p1 = points[0][1]        p2 = points[1][1]        z0 = p1[2]        lim = int(ceil(self.max_radius / conv.pixelsize))        r = range(1, lim)        if self.feed:            conv.g.set_feed(self.feed)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -