示例#1
0
文件: draw.py 项目: e76nystrom/pnc
 def arc(self, end, center, layer=None):
     if self.enable:
         r = xyDist(end, center)
         if self.svg is not None:
             self.path.push_arc(self.scaleOffset(end), 0, r, \
                                 large_arc=True, angle_dir='+', \
                                 absolute=True)
         if self.d is not None:
             if layer is None:
                 layer = self.lPath
             else:
                 if not layer in self.definedLayers:
                     self.definedLayers[layer] = True
                     self.d.add_layer(layer, color=self.color, lineweight=0)
             p0 = self.last
             p1 = end
             if xyDist(p0, p1) < MIN_DIST:
                 self.d.add(dxf.circle(r, center, layer=layer))
             else:
                 # dprt("p0 (%7.4f, %7.4f) p1 (%7.4f, %7.4f)" % \
                 #      (p0[0], p0[1], p1[0], p1[1]))
                 # if orientation(p0, center, p1) == CCW:
                 #     (p0, p1) = (p1, p0)
                 a0 = degrees(calcAngle(center, p0))
                 a1 = degrees(calcAngle(center, p1))
                 if a1 == 0.0:
                     a1 = 360.0
                 # dprt("a0 %5.1f a1 %5.1f" % (a0, a1))
                 self.d.add(dxf.arc(r, center, a0, a1, layer=layer))
             self.last = end
示例#2
0
 def trim(self, path):
     dprt("trim start %d trimX %7.4f trimy %7.4f xPlus %5s yPlus %5s" % \
          (self.layerNum, self.trimX, self.trimY, self.xPlus, self.yPlus))
     if self.layerNum == 3:
         dprt("break")
     rtnPath = []
     for l in path:
         if l.index == INDEX_MARKER:
             continue
         if l.type == ARC:
             if xyDist((self.trimX, self.trimY), l.c) < l.r:
                 continue
         # elif l.type == LINE:
         #     rtnPath.append(l)
         #     continue
         dprt()
         l.prt()
         dprt("horz trim")
         l1 = l.horizontalTrim(self.trimY, self.yPlus)
         if l1 != None:
             l1.prt()
             dprt("vert trim")
             l1 = l.verticalTrim(self.trimX, self.xPlus)
             if l1 != None:
                 l1.prt()
                 rtnPath.append(l1)
             else:
                 dprt("vert returned None")
         else:
             dprt("horz returned None")
     dprt("\ntrim done")
     return (rtnPath)
示例#3
0
 def pointsArc(self, p0, p1, p2, dbg=False):
     if dbg:
         dprt("p0 (%7.4f %7.4f) p1 (%7.4f %7.4f) "\
              "p2 (%7.4f %7.4f) %7.4f %7.4f" % \
              (p0[0], p0[1], p1[0], p1[1], p2[0], p2[1], \
               xyDist(p0, p1), xyDist(p1, p2)))
     (eqType0, m0, b0) = self.lineMid90(p0, p1, dbg)
     (eqType1, m1, b1) = self.lineMid90(p1, p2, dbg)
     if dbg:
         dprt("eqType0 %5s m0 %7.4f b0 %7.4f "\
              "eqType1 %5s m1 %7.4f b1 %7.4f" % \
              (eqType0, m0, b0, eqType1, m1, b1))
     if eqType0:
         if eqType1:
             # y = m0*x + b0
             # y = m1*x + b1
             # m0*x + b0 = m1*x + b1
             # x*(m0 - m1) = b1 - b0
             x = (b1 - b0) / (m0 - m1)
             y = m0 * x + b0
         else:
             # y = m0*x + b0
             # x = m1*y + b1
             # y = m0 * (m1*y + b1) + b0
             # y = m0*m1*y + m0*b1 + b0
             # y - m0*m1*y = m0*b1 + b0
             # y * (1 - m0*m1) = m0*b1 + b0
             # y = (m0*b1 + b0) / (1 - m0*m1)
             y = (m0*b1 + b0) / (1 - m0*m1)
             x = m1 * y + b1
     else:
         if eqType1:
             x = (m0*b1 + b0) / (1 - m0*m1)
             y = m1 * x + b1
         else:
             y = (b1 - b0) / (m0 - m1)
             x = m0 * y + b0
     c = (x, y)
     r0 = xyDist(c, p0)
     if dbg:
         r1 = xyDist(c, p1)
         r2 = xyDist(c, p2)
         dprt("c (%7.4f %7.4f) r0 %7.4f r1 %7.4f r2 %7.4f" % \
              (c[0], c[1], r0, r1, r2))
     return((c, r0))
示例#4
0
 def closest(self, path):
     p0 = self.last
     minD = MAX_VALUE
     for (i, l) in enumerate(path):
         dist = xyDist(p0, l.p0)
         if dist < minD:
             minD = dist
             index = i
     path = path[index:] + path[:index]
     self.last = path[0].p0
     return(path)
示例#5
0
    def pocket(self, args, dbg=None):
        if dbg is None:
            dbg = self.dbg
        layer = args[1]
        cfg = self.cfg
        # dir = CCW
        # if cfg.dir is not None and cfg.dir == 'CW':
        #     dir = CW
        stepOver = cfg.endMillSize * self.stepOver
        cfg.ncInit()
        segments = cfg.dxfInput.getPath(layer)
        pco = PyclipperOffset()
        mp = cfg.getMillPath()
        self.last = cfg.mill.last
        for seg in segments:
            self.pDir = pathDir(seg)
            pco.Clear()
            mainPath = []
            for (i, l) in enumerate(seg):
                l.draw()
                if dbg:
                    l.prt()
                if l.type == LINE:
                    mainPath.append(intScale(l.p0))
                elif l.type == ARC:
                    self.arcLines(mainPath, l, dbg=dbg)
            if dbg:
                dprt()
                for (i, p) in enumerate(mainPath):
                    (x, y) = floatScale(p)
                    dprt("%3d (%7.4f %7.4f)" % (i, x, y))
                dprt()
            
            pco.AddPath(mainPath, pyclipper.JT_ROUND, \
                        pyclipper.ET_CLOSEDPOLYGON)
            offset = cfg.endMillSize / 2.0 + cfg.finishAllowance
            step = 0
            offsetPaths = []
            while True:
                result = pco.Execute(-int(offset * SCALE))
                if dbg:
                    dprt("%2d offset %7.4f results %d" % \
                         (step, offset, len(result)))
                if len(result) == 0:
                    break
                rData = []
                for (rNum, r) in enumerate(result):

                    # convert from list of points to lines

                    if self.arcs:
                        pLast = floatScale(r[-1])
                        index = 0
                        maxDist = -1
                        for (i, p) in enumerate(r):
                            p = floatScale(p)
                            dist = xyDist(p, pLast)
                            if dbg:
                                dprt("%3d (%7.4f %7.4f) dist %9.6f" % \
                                     (i, p[0], p[1], dist))
                            if dist > maxDist:
                                maxDist = dist
                                index = i
                            r[i] = p
                            pLast = p
                        r = r[index:] + r[:index]
                        if dbg:
                            dprt("index %d maxDist %7.4f" % (index, maxDist))
                            pLast = r[-1]
                            dprt("pLast (%7.4f %7.4f)" % (pLast[0], pLast[1]))
                            for (i, p) in enumerate(r):
                                dprt("%3d (%7.4f %7.4f) dist %9.6f" % \
                                     (i, p[0], p[1], xyDist(p, pLast)))
                                pLast = p
                                dprt()
                        path = self.makePath(r, step, rNum, dbg)
                    else:
                        pLast = floatScale(r[-1])
                        path = []
                        for (i, p) in enumerate(r):
                            p = floatScale(p)
                            if dbg:
                                dprt("%3d (%7.4f %7.4f)" % (i, p[0], p[1]))
                            l = Line(pLast, p, i)
                            txt = "s %d r %d i %d" % (step, rNum, i)
                            l.label(txt)
                            path.append(l)
                            pLast = p

                    result[rNum] = path
                        
                    if dbg:
                        dprt()
                        for l in path:
                            l.prt()
                        dprt()

                    # find shortest distance to each path

                    oData = []
                    for (oNum, oPath) in enumerate(offsetPaths):
                        lEnd = oPath[-1]
                        pEnd = lEnd.p1
                        minDist = MAX_VALUE
                        index = None
                        for (i, l) in enumerate(path):
                            dist = xyDist(pEnd, l.p0)
                            if dist < minDist:
                                minDist = dist
                                index = i
                        oData.append((index, minDist))
                    rData.append(oData)
                
                # connect to nearest path

                if dbg and len(result) > 1:
                    dprt("multiple results")
                oConnect = [False] * len(offsetPaths)
                while True:
                    minDist = MAX_VALUE
                    index = None
                    rPath = None
                    for (rNum, oData) in enumerate(rData):
                        if oData == None:
                            continue
                        rPath = rNum
                        for (oNum, (i, dist)) in enumerate(oData):
                            if dbg:
                                dprt("step %d rNum %d Onum %d index %3d "\
                                     "dist %9.6f" % \
                                     (step, rNum, oNum, i, dist))
                            if not oConnect[oNum] and dist < minDist:
                                minDist = dist
                                index = i
                                rIndex = rNum
                                oIndex = oNum
                                
                    if rPath is None:
                        break
                    if index is not None: # connect path
                        if dbg:
                            dprt("connect rIndex %d index %3d to "\
                                 "oIndex %d dist %9.6f" % \
                                 (rIndex, index, oIndex, minDist))
                        path = result[rIndex]
                        rData[rIndex] = None
                        oConnect[oIndex] = True
                        oPath = offsetPaths[oIndex]
                        oPath.append(Line(oPath[-1].p1, path[index].p0))
                        oPath += path[index:] + path[:index]
                    else:       # add new path
                        if dbg:
                            dprt("add rPath %d oNum %d" % \
                                 (rPath, len(offsetPaths)))
                        rData[rPath] = None
                        path = result[rPath]
                        path = self.closest(path)
                        offsetPaths.append(path)

                offset += stepOver
                step += 1
                if step > 99:
                    break
            for path in offsetPaths:
                mp.millPath(path, closed=False, minDist=False)
示例#6
0
    def makePath(self, points, step, rNum, dbg=False):
        if False:
            r = 1
            for i in range(4):
                a0 = float(i) * pi / 2 + pi / 4
                a = a0
                p0 = (r * cos(a), r * sin(a))
                for j in range(2):
                    tmp = (pi, -pi)[j]
                    a = a0 + tmp / 2
                    p1 = (r * cos(a), r * sin(a))
                    a = a0 + tmp / 1
                    p2 = (r * cos(a), r * sin(a))
                    self.pointsArc(p0, p1, p2)
            dprt()
            sys.exit()

        numPoints = len(points)
        pLast = points[-1]
        i = 0
        path = []
        # points.append(points[0])
        o0 = orientation(pLast, points[0], points[1])
        if dbg:
            dprt("path orientation %s" % oStr(o0))
        while i < numPoints:
            p0 = points[i]
            if dbg:
                dprt("i %3d (%7.4f %7.4f)" % (i, p0[0], p0[1]))
            d0 = xyDist(p0, pLast)
            j = i + 1
            pa = p0
            while j < numPoints - 1:
                pj = points[j]
                dist = xyDist(pa, pj)
                if abs(dist - d0) > 0.001:
                    if dbg:
                        dprt("dist %9.6f d0 %9.6f" % (dist, d0))
                    break
                j += 1
                pa = pj
            delta = j - i
            if delta < 4:
                l = Line(pLast, p0, i)
                txt = "s %d r %d i %d" % (step, rNum, i)
                l.label(txt)
                i += 1
                pLast = p0
            else:
                p1 = points[i + delta / 2]
                (c, r) = self.pointsArc(pLast, p1, pa)
                o = orientation(pLast, p1, pa)
                if o != o0:
                    (pLast, pa) = (pa, pLast)
                a0 = degAtan2(pLast[1] - c[1], pLast[0] - c[0])
                a1 = degAtan2(pa[1] - c[1], pa[0] - c[0])
                l = Arc(c, r, a0, a1, direction=o)
                if dbg:
                    dprt("arc %s %2d i %d (%7.4f %7.4f) %8.3f "\
                         " %d (%7.4f %7.4f) %8.3f" % \
                         (oStr(o), delta, i, pLast[0], pLast[1], a0, \
                          j, pa[0], pa[1], a1))
                i = j
                pLast = pa
            if dbg:
                l.prt()
            path.append(l)
        return(path)
示例#7
0
    def enlargeHole(self, args):
        outerLayer = args[1]
        try:
            innerD = self.cfg.evalFloatArg(args[2])
            innerLayer = None
        except ValueError:
            innerLayer = args[2]
        cfg = self.cfg
        direction = CCW
        if cfg.dir is not None and cfg.dir == 'CW':
            direction = CW
        cfg.ncInit()
        # endAngle = self.endAngle
        # swapped = False
        outer = cfg.dxfInput.getCircles(outerLayer)
        if innerLayer is not None:
            inner = cfg.dxfInput.getCircles(innerLayer)
        for (c, outerD) in outer:
            if innerLayer is not None:
                found = False
                for (c0, innerD) in inner:
                    if xyDist(c, c0) < MIN_DIST:
                        found = True
                        break
                if not found:
                    continue
            draw = cfg.draw
            if draw is not None:
                draw.circle(c, innerD / 2.0)
                draw.circle(c, outerD / 2.0)
            outerD -= 2 * cfg.finishAllowance
            totalDist = (outerD - innerD) / 2
            passes = int(round(totalDist / self.distPass))
            distPass = totalDist / passes
            endMillRadius = cfg.endMillSize / 2.0
            (xC, yC) = c

            self.path = []
            self.index = 0
            r0 = innerD / 2.0 - endMillRadius
            if self.leadRadius != 0:
                leadCenter = (r0 - self.leadRadius + xC, yC)
                if direction == CCW:
                    self.addSeg(
                        Arc(leadCenter, self.leadRadius, 270, 0,
                            direction=CCW))
                else:
                    self.addSeg(
                        Arc(leadCenter, self.leadRadius, 0, 90, direction=CW))

            for _ in range(passes):
                r1 = r0 + distPass
                y1 = sqrt(r1 * r1 - r0 * r0)
                p0 = (xC + r0, yC)

                if direction == CCW:
                    p1 = (xC + r0, yC + y1)
                else:
                    p1 = (xC + r0, yC - y1)

                self.addSeg(Line(p0, p1))

                a0 = degrees(atan2(y1, r0))
                if direction == CCW:
                    self.addSeg(Arc(c, r1, a0, 0, direction=CCW))
                else:
                    self.addSeg(Arc(c, r1, 0, a0, direction=CW))
                r0 = r1
            self.addSeg(Arc(c, r1, 0, a0, direction=direction))

            if self.leadRadius != 0:
                r2 = r1 - self.leadRadius
                a0R = radians(a0)
                leadCenter = (r2 * cos(a0R) + xC, r2 * sin(a0R) + yC)
                if direction == CCW:
                    self.addSeg(
                        Arc(leadCenter,
                            self.leadRadius,
                            a0,
                            a0 + 90,
                            direction=CCW))
                else:
                    self.addSeg(
                        Arc(leadCenter,
                            self.leadRadius,
                            a0 - 90,
                            a0,
                            direction=CW))
            self.millPath()
示例#8
0
    def rectSlot(self, args):
        layer = args[1]
        cfg = self.cfg
        cfg.ncInit()
        segments = cfg.dxfInput.getPath(layer)
        millSeg = []
        for seg in segments:
            if len(seg) != 4:
                ePrint("rectPocket wrong number of sides")
                continue
            vert = []
            horiz = []
            arc = []
            for l in seg:
                if l.type == LINE:
                    if abs(l.p0[0] - l.p1[0]) < MIN_DIST:
                        vert.append(l)
                    elif abs(l.p0[1] - l.p1[1]) < MIN_DIST:
                        horiz.append(l)
                elif l.type == ARC:
                    arc.append(l)
                    
            if len(arc) == 2:
                if abs(arc[0].r - cfg.endMillSize / 2.0) < MIN_DIST:
                    path = []
                    path.append(Line(arc[0].c, arc[1].c))
                    millSeg.append(path)
                else:
                    a0 = arc[0]
                    a1 = arc[1]
                    if len(vert) == 2:
                        x = a0.p0.x
                        if a0.c.y > a1.c.y:
                            (a0, a1) = (a1, a0)
                        y = a0.c.y + (a1.c.y - a0.c.y) / 2
                        w = abs(a0.p0.x - a0.p1.x)
                        h = abs(a0.c.y - a1.c.y)
                        self.pocket(x, y, w, h)
                    elif len(horiz) == 2:
                        if a0.c.x > a1.c.y:
                            (a0, a1) = (a1, a0)
                        x = a0.c.x + (a1.c.x - a0.c.x) / 2
                        y = a0.p0.y
                        w = abs(a0.c.x - a1.c.x)
                        h = abs(a0.p0.y - a1.p1.y)
                        self.pocket(x, y, w, h)
            
        last = cfg.mill.last
        mp = cfg.getMillPath()
        while len(millSeg):
            minDist = MAX_VALUE
            index = None
            for i, path in enumerate(millSeg):
                dist0 = xyDist(last, path[0].p0)
                dist1 = xyDist(last, path[-1].p1)
                if dist0 < dist1:
                    dist = dist0
                    swap = False
                else:
                    dist = dist1
                    swap = True
                if dist < minDist:
                    minDist = dist
                    minSwap = swap
                    index = i

            path = millSeg.pop(index)
            if swap:
                path = reverseSeg(path, False)
            mp.millPath(path, closed=False)