def get_paths(self, use_symmetry=True): if self.paths is not None: if use_symmetry: return [item for sublist in self.paths for item in sublist] else: return self.paths[0] # simplify / rotate shape self.paths = [] for i in xrange(self.symmetry): self.paths.append([]) xform = ( TransformMatrix.translate(self.origin) * TransformMatrix.rotateAxis( Point(0,0,1), angle=2*pi*i/self.symmetry ) * TransformMatrix.translate(-self.origin) ) for node in self.effect.layer_contents(self.layer): if node.tag == inkex.addNS('path', 'svg'): xform2 = xform * TransformMatrix.fromSVG( simpletransform.parseTransform(node.get('transform')) ) d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, FLATNESS) for sp in p: thisPath = [] for csp in sp: thisPath.append( Point(csp[1][0],csp[1][1],0).transform(xform2) ) self.paths[i].append(thisPath) return self.get_paths(use_symmetry)
def effect(self): gcode = "" i = 0 doc = self.document.getroot() factor = self.unittouu(doc.get('width')) inkex.debug(factor) for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] first = True gcode = "M3 S255(colona " + str(i) + ") \n" #+"G01 F500.000\n" for csp in p[0]: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) gcode += "G01 X" + str( round(self.uutounit(csp[1][0], "mm"), 2)) + " Y" + str( round(self.uutounit(csp[1][1], "mm"), 2)) + "\n" node.set('d', simplepath.formatPath(np)) f = open("costycnc.nc", 'w') f.write(str(gcode)) f.close()
def __call__(self, curve): """ Flattens the given curve Code is taken from flatten.py :param curve: the description of the curve to flatten. This must be the value of the "d" parameter of the svg path element :type curve: string :return: the flattened curve :rtype: a list containing the flattened curve. The format is the same as the one returned by simplepath.parsePath """ if curve == "": return [] p = cubicsuperpath.parsePath(curve) # pylint: disable=invalid-name cspsubdiv.cspsubdiv(p, self.flatness) np = [] # pylint: disable=invalid-name for sp in p: # pylint: disable=invalid-name first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) return np
def flatten(self, path): """approximate a path containing beziers with a series of points""" path = deepcopy(path) cspsubdiv(path, 0.1) return [self.strip_control_points(subpath) for subpath in path]
def process_layer(self, layer_element, layer_name): #For each layer group, get each path. for element in layer_element.iter(tag_path): log("Found path: " + str(element.attrib['d'])) #Get the point transform at node svg_transforms = self.get_transform_list(element) #Parse path parsed_path = cubicsuperpath.parsePath(element.attrib['d']) #Convert into polyline cspsubdiv.cspsubdiv(parsed_path, self.resolution) #At this point, parsed_path contains a list of list of points (yes, I know) #so for each "path", each "subpath" we should get an array of points for subpath in parsed_path: log(" Subpath (%d points)" % len(subpath)) #Write footprint path begining self.out_file.write(polygon_header) for point in subpath: point = list(point[1]) for transform in svg_transforms: log("Applying transform: " + str(transform)) simpletransform.applyTransformToPoint(transform, point) log(" Point: " + str(point)) #transform point using self.transform matrix #write individual point self.out_file.write("(xy %f %f) " % (point[0], point[1])) self.out_file.write(polygon_footer.format(layer=layer_name))
def dxf_path_to_lines(self, layer, p, color=None): f = self.flatness is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, f) is_flat = 1 except IndexError: break except: f += 0.1 if f > 2: # something has gone very wrong. break lines = '' for sub in p: codes = [] if color is not None: dxf_color_val = str(self.dxf_color.color_value(color)) codes = [('62', dxf_color_val,)] codes += [ ('0', 'LWPOLYLINE'), ('100', 'AcDbPolyline'), ('8', layer), ('90', '%i' % (len(sub))), ('70', '0') ] lines += self.dxf_add_codes(codes) for i in range(len(sub)): self.handle += 1 x = sub[i][1][0] y = sub[i][1][1] # Compare global maxes and mins dims = self.global_dims if dims['minX'] is None or x < dims['minX']: self.global_dims['minX'] = x elif dims['maxX'] is None or x > dims['maxX']: self.global_dims['maxX'] = x if dims['minY'] is None or y < dims['minY']: self.global_dims['minY'] = y elif dims['maxY'] is None or y > dims['maxY']: self.global_dims['maxY'] = y # Compare layer maxes and mins dims = self.layer_dims[layer] if dims['minX'] is None or x < dims['minX']: self.layer_dims[layer]['minX'] = x elif dims['maxX'] is None or x > dims['maxX']: self.layer_dims[layer]['maxX'] = x if dims['minY'] is None or y < dims['minY']: self.layer_dims[layer]['minY'] = y elif dims['maxY'] is None or y > dims['maxY']: self.layer_dims[layer]['maxY'] = y lines += self.dxf_add_codes([ ('10', '%f' % x), ('20', '%f' % y), ('30', '0.0') ]) return lines
def effect(self): """ This method is called first, and sets up the self.commands list for later output. """ svg = self.document.getroot() # find document width and height, used to scale down self.doc_width = inkex.unittouu(svg.get('width')) self.doc_height = inkex.unittouu(svg.get('height')) # add header self.commands.append("^DF;") self.commands.append("! 1;") self.commands.append("H;") self.commands.append("@ %d %d;" % (self.options.z_down, self.options.z_up)) self.commands.append("V {0};F {0};\n".format(self.options.feed_rate_moving)) self.commands.append("Z 0 0 %d;" % self.options.z_up) # mostly borrowed from hgpl_output.py lastX = 0 lastY = 0 # find paths in layers i = 0 layerPath = '//svg:g[@inkscape:groupmode="layer"]' for layer in svg.xpath(layerPath, namespaces=inkex.NSS): i += 1 nodePath = ('//svg:g[@inkscape:groupmode="layer"][%d]/descendant::svg:path') % i for node in svg.xpath(nodePath, namespaces=inkex.NSS): # these next lines added from this patch to fix the transformation issues - http://launchpadlibrarian.net/36269154/hpgl_output.py.patch # possibly also want to try this code: https://bugs.launchpad.net/inkscape/+bug/600472/+attachment/1475310/+files/hpgl_output.py transforms = node.xpath("./ancestor-or-self::svg:*[@transform]",namespaces=inkex.NSS) matrix = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] for parenttransform in transforms: newmatrix = simpletransform.parseTransform(parenttransform.get("transform")) matrix = simpletransform.composeTransform(matrix, newmatrix) d = node.get('d') if len(simplepath.parsePath(d)): p = cubicsuperpath.parsePath(d) simpletransform.applyTransformToPath(matrix, p) # this line is also from the transform-fixing patch mentioned above cspsubdiv.cspsubdiv(p, self.options.flat) for sp in p: first = True for csp in sp: if first: x, y = self.conv_coords(csp[1][0], self.doc_height - csp[1][1]) self.commands.append("Z %d %d %d;" % (x, y, self.options.z_up)) self.commands.append("V {0};F {0};".format(self.options.feed_rate_cutting)) first = False x, y = self.conv_coords(csp[1][0], self.doc_height - csp[1][1]) self.commands.append("Z %d %d %d;" % (x, y, self.options.z_down)) lastX = x lastY = y self.commands.append("V {0};F {0};".format(self.options.feed_rate_moving)) self.commands.append("Z %d %d %d;" % (lastX, lastY, self.options.z_up)) self.commands.append("Z 0 0 %d;" % self.options.z_up) self.commands.append("H;")
def csv_path_to_stitches(self, pth): """""" f = self.flatness cspsubdiv.cspsubdiv(pth, f) for subPath in pth: for i in range(len(subPath)): s = subPath[i] if not i: self.csv_append_jump(s[0][0], s[0][1]) self.csv_append_stitch(s[0][0], s[0][1])
def _readPath(self, item, flat, transform): p = cubicsuperpath.parsePath(item.get('d')) cspsubdiv.cspsubdiv(p, flat) subpaths = [] for sp in p: sps = [] subpaths.append(sps) for c0, c1, c2 in sp: pt = list(c2) simpletransform.applyTransformToPoint(transform, pt) sps.append(tuple(pt)) self[:] = mergePaths(sortPaths(subpaths))
def effect(self): # get page size: root_doc = self.document.getroot() viewbox = root_doc.attrib['viewBox'] # width = root_doc.attrib['width'] # height = root_doc.attrib['height'] splitbox = viewbox.split(' ') fconv = float(self.unittouu(self.options.unit)) x1 = float(splitbox[0]) y1 = float(splitbox[1]) # x2 = float(splitbox[2]) y2 = float(splitbox[3]) # w = float(self.unittouu(width)) # h = float(self.unittouu(height)) # Flatten path(s) and format polygon as a string outputString = "" for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False outputString += str( (csp[1][0] - x1) / fconv) + "\t" + str( (y2 - csp[1][1] + y1) / fconv) + "\n" outputString += "\n" # get the filename to write to path = self.options.filepath if (path != None): if (not os.path.isabs(path)): if os.name == 'nt': path = os.path.join(os.environ['USERPROFILE'], path) else: path = os.path.join(os.path.expanduser("~"), path) f = open(path, 'w') f.write(outputString) f.close inkex.errormsg('polygon extracted to: %s' % path) else: outputString = ( "# No filename was provided, using stderr\n") + outputString sys.stderr.write(outputString)
def curveto(p0,curve,flat): poly = [] d = simplepath.formatPath([['M',p0],curve]) p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, flat) for sp in p: first = True for csp in sp: if first: first = False else: for subpath in csp: poly.append(['L',list(subpath)]) return poly
def appendPolygonsFromPath(self, d, layer, style): fill = True if style.has_key('fill'): fill = style['fill'] if not fill or fill == 'none': return # ix.debug('appendPolygonsFromPath') path = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(path, self.options.flatness) path = listit(path) simpletransform.applyTransformToPath(self.currentTransform(), path) polygons = constructBridgedPolygonsFromPath(path) for polygon in polygons: self.appendPolygon(polygon, layer)
def curveto(p0, curve, flat): poly = [] d = simplepath.formatPath([['M', p0], curve]) p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, flat) for sp in p: first = True for csp in sp: if first: first = False else: for subpath in csp: poly.append(['L', list(subpath)]) return poly
def flatten(p, flat=10.0, round_to_int=True): """ Flatten a bezier curve to polylines or simple x,y coordinates Arguments: * p: path array * flat: Flattening degree """ cspsubdiv.cspsubdiv(p, flat) stroke = [] for sp in p: for csp in sp: stroke.append({"x": round(csp[1][0]), "y": round(csp[1][1])}) return stroke
def effect(self): path = '//svg:path' for node in self.document.getroot().xpath(path, namespaces=inkex.NSS): d = node.get('d') if len(simplepath.parsePath(d)): p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) for sp in p: first = True for csp in sp: cmd = 'PD' if first: cmd = 'PU' first = False self.hpgl.append('%s%s,%s;' % (cmd,csp[1][0],csp[1][1]))
def processPath(self, node, mat, pen): # process path path = node.get('d') if path: # parse and transform path path = cubicsuperpath.parsePath(path) simpletransform.applyTransformToPath(mat, path) cspsubdiv.cspsubdiv(path, self.flat) # path to HPGL commands oldPosX = 0.0 oldPosY = 0.0 for singlePath in path: cmd = 'PU' for singlePathPoint in singlePath: posX, posY = singlePathPoint[1] # check if point is repeating, if so, ignore if int(round(posX)) != int(round(oldPosX)) or int( round(posY)) != int(round(oldPosY)): self.processOffset(cmd, posX, posY, pen) cmd = 'PD' oldPosX = posX oldPosY = posY # perform overcut if self.overcut > 0.0 and not self.dryRun: # check if last and first points are the same, otherwise the path is not closed and no overcut can be performed if int(round(oldPosX)) == int(round( singlePath[0][1][0])) and int( round(oldPosY)) == int( round(singlePath[0][1][1])): overcutLength = 0 for singlePathPoint in singlePath: posX, posY = singlePathPoint[1] # check if point is repeating, if so, ignore if int(round(posX)) != int(round(oldPosX)) or int( round(posY)) != int(round(oldPosY)): overcutLength += self.getLength( oldPosX, oldPosY, posX, posY) if overcutLength >= self.overcut: newLength = self.changeLength( oldPosX, oldPosY, posX, posY, -(overcutLength - self.overcut)) self.processOffset(cmd, newLength[0], newLength[1], pen) break else: self.processOffset(cmd, posX, posY, pen) oldPosX = posX oldPosY = posY
def dxf_path_to_lines(self,layer,p): f = self.flatness is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, self.flatness) is_flat = 1 except: f += 0.1 for sub in p: for i in range(len(sub)-1): self.handle += 1 s = sub[i] e = sub[i+1] self.dxf_line(layer,[s[1],e[1]])
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd,[csp[1][0],csp[1][1]]]) node.set('d',simplepath.formatPath(np))
def flatten(self, path): """approximate a path containing beziers with a series of points""" path = deepcopy(path) cspsubdiv(path, 0.1) flattened = [] for comp in path: vertices = [] for ctl in comp: vertices.append((ctl[1][0], ctl[1][1])) flattened.append(vertices) return flattened
def effect(self): for id, node in self.selected.iteritems(): if node.tagName == 'path': d = node.attributes.getNamedItem('d') p = cubicsuperpath.parsePath(d.value) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd,[csp[1][0],csp[1][1]]]) d.value = simplepath.formatPath(np)
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) node.set('d', simplepath.formatPath(np))
def effect(self): for id, node in self.selected.iteritems(): if node.tagName == 'path': d = node.attributes.getNamedItem('d') p = cubicsuperpath.parsePath(d.value) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) d.value = simplepath.formatPath(np)
def effect(self): path = '//svg:path' for node in self.document.getroot().xpath(path, namespaces=inkex.NSS): d = node.get('d') if len(simplepath.parsePath(d)): p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) for sp in p: first = True for csp in sp: cmd = 'PD' if first: cmd = 'PU' first = False self.hpgl.append('%s%s,%s;' % (cmd, csp[1][0], csp[1][1]))
def process_path(self, node, mat): d = node.get('d') if d: p = cubicsuperpath.parsePath(d) trans = node.get('transform') if trans: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, p) cspsubdiv.cspsubdiv(p, self.options.flat) for sp in p: first = True for csp in sp: cmd = 'PD' if first: cmd = 'PU' first = False self.hpgl.append('%s%d,%d;' % (cmd,csp[1][0],csp[1][1]))
def process_path(self, node, mat): d = node.get('d') if d: p = cubicsuperpath.parsePath(d) trans = node.get('transform') if trans: mat = simpletransform.composeTransform( mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, p) cspsubdiv.cspsubdiv(p, self.options.flat) for sp in p: first = True for csp in sp: cmd = 'PD' if first: cmd = 'PU' first = False self.hpgl.append('%s%d,%d;' % (cmd, csp[1][0], csp[1][1]))
def processPath(self, p): f = 0.1 is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, f) is_flat = 1 except IndexError: break except: f += 0.1 if f > 2: break for sub in p: for i in range(len(sub)): x = sub[i][1][0] y = sub[i][1][1] yield [x,y]
def flatten_bezier(self): layerPath = '//svg:g[@inkscape:groupmode="layer"][@inkscape:label="Edge.Cuts"]' for layer in self.document.getroot().xpath(layerPath, namespaces=inkex.NSS): nodePath = 'descendant::svg:path' for node in layer.xpath(nodePath, namespaces=inkex.NSS): if node.tag == inkex.addNS('path','svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, 0.01) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) node.set('d', simplepath.formatPath(np))
def flattenPath(node, flat): if node.tag == inkex.addNS('path','svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, flat) np = [] pnts = '' for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False pnts += str(csp[1][0]) + ',' + str(csp[1][1]) + '|' np.append([cmd,[csp[1][0],csp[1][1]]]) node.set('d',simplepath.formatPath(np)) return pnts
def applyOffset(self, poly): # adjust for blade offset #todo, this haha d = abs(self.offset) def angleBetween(axis, p0, p1): def dotP(p0, p1): p = 0 for a1, a2 in zip(p0, p1): p += a1 * a2 return p def norm(p0): n = 0 for a in p0: n += a * a return math.sqrt(n) p0 = [p0[0] - axis[0], p0[1] - axis[1]] p1 = [p1[0] - axis[0], p1[1] - axis[1]] assert norm(p0) > 0 and norm(p1) > 0, "invalid points" r = dotP(p0, p1) / (norm(p0) * norm(p1)) if -1 <= r <= 1: return math.acos(r) else: return math.pi def arcto(radius, theta, (x, y), p0): poly = [] arc = ['A', [radius, radius, theta, 0, 0, x, y]] d = simplepath.formatPath([['M', p0], arc]) p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.smoothness) for sp in p: first = True for csp in sp: if first: first = False else: for subpath in csp: poly.append(['L', list(subpath)]) return poly
def processPath(self, node, mat): # process path paths = node.get('d') if paths: # parse and transform path paths = cubicsuperpath.parsePath(paths) simpletransform.applyTransformToPath(mat, paths) cspsubdiv.cspsubdiv(paths, self.options.flat) # path to HPGL commands oldPosX = 0.0 oldPosY = 0.0 # TODO: Plot smallest parts first to avid plotter dragging parts of foil around (on text) for singlePath in paths: cmd = 'PU' for singlePathPoint in singlePath: posX, posY = singlePathPoint[1] # check if point is repeating, if so, ignore if int(round(posX)) != int(round(oldPosX)) or int(round(posY)) != int(round(oldPosY)): self.processOffset(cmd, posX, posY) cmd = 'PD' oldPosX = posX oldPosY = posY # perform overcut if self.options.useOvercut and not self.dryRun: # check if last and first points are the same, otherwise the path is not closed and no overcut can be performed if int(round(oldPosX)) == int(round(singlePath[0][1][0])) and int(round(oldPosY)) == int(round(singlePath[0][1][1])): overcutLength = 0 for singlePathPoint in singlePath: posX, posY = singlePathPoint[1] # check if point is repeating, if so, ignore if int(round(posX)) != int(round(oldPosX)) or int(round(posY)) != int(round(oldPosY)): overcutLength += self.getLength(oldPosX, oldPosY, posX, posY) if overcutLength >= self.options.overcut: newLength = self.changeLength(oldPosX, oldPosY, posX, posY, - (overcutLength - self.options.overcut)) self.processOffset(cmd, newLength[0], newLength[1]) break else: self.processOffset(cmd, posX, posY) oldPosX = posX oldPosY = posY
def processPath(self, node, mat, pen): # process path path = node.get('d') if path: # parse and transform path path = cubicsuperpath.parsePath(path) simpletransform.applyTransformToPath(mat, path) cspsubdiv.cspsubdiv(path, self.flat) # path to HPGL commands oldPosX = 0.0 oldPosY = 0.0 for singlePath in path: cmd = 'PU' for singlePathPoint in singlePath: posX, posY = singlePathPoint[1] # check if point is repeating, if so, ignore if int(round(posX)) != int(round(oldPosX)) or int(round(posY)) != int(round(oldPosY)): self.processOffset(cmd, posX, posY, pen) cmd = 'PD' oldPosX = posX oldPosY = posY # perform overcut if self.overcut > 0.0 and not self.dryRun: # check if last and first points are the same, otherwise the path is not closed and no overcut can be performed if int(round(oldPosX)) == int(round(singlePath[0][1][0])) and int(round(oldPosY)) == int(round(singlePath[0][1][1])): overcutLength = 0 for singlePathPoint in singlePath: posX, posY = singlePathPoint[1] # check if point is repeating, if so, ignore if int(round(posX)) != int(round(oldPosX)) or int(round(posY)) != int(round(oldPosY)): overcutLength += self.getLength(oldPosX, oldPosY, posX, posY) if overcutLength >= self.overcut: newLength = self.changeLength(oldPosX, oldPosY, posX, posY, - (overcutLength - self.overcut)) self.processOffset(cmd, newLength[0], newLength[1], pen) break else: self.processOffset(cmd, posX, posY, pen) oldPosX = posX oldPosY = posY
def applyOffset(self,poly): # adjust for blade offset #todo, this haha d = abs(self.offset) def angleBetween(axis,p0,p1): def dotP(p0,p1): p = 0 for a1,a2 in zip(p0,p1): p +=a1*a2 return p def norm(p0): n = 0 for a in p0: n +=a*a return math.sqrt(n) p0 = [p0[0]-axis[0],p0[1]-axis[1]] p1 = [p1[0]-axis[0],p1[1]-axis[1]] assert norm(p0) > 0 and norm(p1) > 0, "invalid points" r = dotP(p0,p1)/(norm(p0)*norm(p1)) if -1 <= r <= 1: return math.acos(r) else: return math.pi def arcto(radius,theta,(x,y),p0): poly = [] arc = ['A',[radius,radius,theta,0,0,x,y]] d = simplepath.formatPath([['M',p0],arc]) p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.smoothness) for sp in p: first = True for csp in sp: if first: first = False else: for subpath in csp: poly.append(['L',list(subpath)]) return poly
def effect(self): gcode = "" for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, self.options.flat) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd, [csp[1][0], csp[1][1]]]) gcode += "G01 X" + str(csp[1][0]) + " Y" + str( csp[1][1]) + "\n" inkex.debug(csp[1][0]) inkex.debug(csp[1][1]) node.set('d', simplepath.formatPath(np)) f = open("costycnc.nc", 'w') f.write(str(gcode)) f.close()
def process_shape(self, node, mat): rgb = (0,0,0) path_id = node.get('id') style = node.get('style') self.Cut_Type[path_id]="raster" # Set default type to raster color_props_fill = ('fill', 'stop-color', 'flood-color', 'lighting-color') color_props_stroke = ('stroke',) color_props = color_props_fill + color_props_stroke ##################################################### ## The following is ripped off from Coloreffect.py ## ##################################################### if style: declarations = style.split(';') for i,decl in enumerate(declarations): parts = decl.split(':', 2) if len(parts) == 2: (prop, col) = parts prop = prop.strip().lower() #if prop in color_props: if prop == 'stroke': col= col.strip() if simplestyle.isColor(col): c=simplestyle.parseColor(col) new_val='#'+self.colmod(c[0],c[1],c[2],path_id) else: new_val = col if new_val != col: declarations[i] = prop + ':' + new_val node.set('style', ';'.join(declarations)) ##################################################### if node.tag == inkex.addNS('path','svg'): d = node.get('d') if not d: return p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('rect','svg'): x = float(node.get('x')) y = float(node.get('y')) width = float(node.get('width')) height = float(node.get('height')) #d = "M %f,%f %f,%f %f,%f %f,%f Z" %(x,y, x+width,y, x+width,y+height, x,y+height) #p = cubicsuperpath.parsePath(d) rx = 0.0 ry = 0.0 if node.get('rx'): rx=float(node.get('rx')) if node.get('ry'): ry=float(node.get('ry')) if max(rx,ry) > 0.0: if rx==0.0 or ry==0.0: rx = max(rx,ry) ry = rx msg = "rx = %f ry = %f " %(rx,ry) inkex.errormsg(_(msg)) L1 = "M %f,%f %f,%f " %(x+rx , y , x+width-rx , y ) C1 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width , y+ry ) L2 = "M %f,%f %f,%f " %(x+width , y+ry , x+width , y+height-ry) C2 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width-rx , y+height ) L3 = "M %f,%f %f,%f " %(x+width-rx , y+height , x+rx , y+height ) C3 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x , y+height-ry) L4 = "M %f,%f %f,%f " %(x , y+height-ry, x , y+ry ) C4 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+rx , y ) d = L1 + C1 + L2 + C2 + L3 + C3 + L4 + C4 else: d = "M %f,%f %f,%f %f,%f %f,%f Z" %(x,y, x+width,y, x+width,y+height, x,y+height) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('circle','svg'): cx = float(node.get('cx') ) cy = float(node.get('cy')) r = float(node.get('r')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" %(cx+r,cy, r,r,cx,cy+r, r,r,cx-r,cy, r,r,cx,cy-r, r,r,cx+r,cy) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('ellipse','svg'): cx = float(node.get('cx')) cy = float(node.get('cy')) rx = float(node.get('rx')) ry = float(node.get('ry')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" %(cx+rx,cy, rx,ry,cx,cy+ry, rx,ry,cx-rx,cy, rx,ry,cx,cy-ry, rx,ry,cx+rx,cy) p = cubicsuperpath.parsePath(d) else: return trans = node.get('transform') if trans: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, p) ################################################### ## Break Curves down into small lines ################################################### f = self.flatness is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, f) is_flat = 1 except IndexError: break except: f += 0.1 if f>2 : break #something has gone very wrong. ################################################### for sub in p: for i in range(len(sub)-1): s = sub[i] e = sub[i+1] self.dxf_line([s[1],e[1]],0.025,rgb,path_id)
def effect(self): for id, shape in self.selected.items(): self.recursiveFuseTransform(shape, parseTransform(None)) #inkex.debug("sunt in shape") to_mm = lambda value: self.uutounit(value, 'mm') doc_heigh = to_mm(self.unittouu(self.document.getroot().get('height'))) gcode = "" pathc = [[0, 0]] path_all = [] path_one = [] i = 0 for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): self.recursiveFuseTransform(shape, parseTransform(None)) d = node.get('d') p = cubicsuperpath.parsePath(d) cspsubdiv.cspsubdiv(p, 0.1) for sp in p: for csp in sp: path_one.append([csp[0][0], doc_heigh - csp[0][1]]) path_all.append(path_one) path_one = [] num0 = 0 num1 = 0 num2 = 0 currDiff = 0 path_final = [[0, 0]] while len(path_all): minDiff = sys.maxint for i in range(len(path_final)): for m in range(len(path_all)): for n in range(len(path_all[m])): x = path_final[i][0] y = path_final[i][1] x1 = path_all[m][n][0] y1 = path_all[m][n][1] x2 = x - x1 y2 = y - y1 currDiff = x2 * x2 + y2 * y2 if currDiff < minDiff: minDiff = currDiff pos0 = i pat1 = m pos1 = n p_tmp = path_all.pop(pat1) #extract p_tmp = p_tmp[pos1:] + p_tmp[:pos1] p_tmp = p_tmp + p_tmp[:1] path_final = path_final[:pos0 + 1] + p_tmp + path_final[pos0:] #path_final[:pos0+1] because read until pos0 and need to read also pos0 gcode = "M3 S255\n" gcode += "G01 X0 Y0\n" i = 0 for i in range(len(path_final) - 1): gcode += "G01 X" + str( round(self.uutounit(path_final[i][0], "mm"), 2)) + " Y" + str( round(self.uutounit(path_final[i][1], "mm"), 2)) + "\n" gcode += "G01 X0 Y0\n" f = open("costycnc.nc", 'w') inkex.debug(gcode) f.write(str(gcode)) f.close()
def process_shape(self, node, mat): rgb = (0, 0, 0) path_id = node.get('id') style = node.get('style') self.Cut_Type[path_id] = "raster" # Set default type to raster #color_props_fill = ('fill', 'stop-color', 'flood-color', 'lighting-color') #color_props_stroke = ('stroke',) #color_props = color_props_fill + color_props_stroke ##################################################### ## The following is ripped off from Coloreffect.py ## ##################################################### if style: declarations = style.split(';') i_sw = -1 sw_flag = False sw_prop = 'stroke-width' for i, decl in enumerate(declarations): parts = decl.split(':', 2) if len(parts) == 2: (prop, col) = parts prop = prop.strip().lower() #if prop in color_props: if prop == sw_prop: i_sw = i if prop == 'stroke': col = col.strip() if simplestyle.isColor(col): c = simplestyle.parseColor(col) new_val = '#' + self.colmod( c[0], c[1], c[2], path_id) else: new_val = col if new_val != col: declarations[i] = prop + ':' + new_val sw_flag = True if sw_flag == True: if node.tag == inkex.addNS('text', 'svg'): if (self.txt2paths == False): raise SVG_TEXT_EXCEPTION( "SVG File with Color Coded Text Outlines Found: (i.e. Blue: engrave/ Red: cut)" ) else: line1 = "SVG File with color coded text outlines found (i.e. Blue: engrave/ Red: cut)." line2 = "Automatic conversion to paths failed: Try upgrading to Inkscape .90 or later" line3 = "To convert manually in Inkscape: select the text then select \"Path\"-\"Object to Path\" in the menu bar." raise StandardError("%s\n\n%s\n\n%s" % (line1, line2, line3)) if i_sw != -1: declarations[i_sw] = sw_prop + ':' + "0.0" else: declarations.append(sw_prop + ':' + "0.0") node.set('style', ';'.join(declarations)) ##################################################### if node.tag == inkex.addNS('path', 'svg'): d = node.get('d') if not d: return p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('rect', 'svg'): x = float(node.get('x')) y = float(node.get('y')) width = float(node.get('width')) height = float(node.get('height')) #d = "M %f,%f %f,%f %f,%f %f,%f Z" %(x,y, x+width,y, x+width,y+height, x,y+height) #p = cubicsuperpath.parsePath(d) rx = 0.0 ry = 0.0 if node.get('rx'): rx = float(node.get('rx')) if node.get('ry'): ry = float(node.get('ry')) if max(rx, ry) > 0.0: if rx == 0.0 or ry == 0.0: rx = max(rx, ry) ry = rx L1 = "M %f,%f %f,%f " % (x + rx, y, x + width - rx, y) C1 = "A %f,%f 0 0 1 %f,%f" % (rx, ry, x + width, y + ry) L2 = "M %f,%f %f,%f " % (x + width, y + ry, x + width, y + height - ry) C2 = "A %f,%f 0 0 1 %f,%f" % (rx, ry, x + width - rx, y + height) L3 = "M %f,%f %f,%f " % (x + width - rx, y + height, x + rx, y + height) C3 = "A %f,%f 0 0 1 %f,%f" % (rx, ry, x, y + height - ry) L4 = "M %f,%f %f,%f " % (x, y + height - ry, x, y + ry) C4 = "A %f,%f 0 0 1 %f,%f" % (rx, ry, x + rx, y) d = L1 + C1 + L2 + C2 + L3 + C3 + L4 + C4 else: d = "M %f,%f %f,%f %f,%f %f,%f Z" % ( x, y, x + width, y, x + width, y + height, x, y + height) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('circle', 'svg'): cx = float(node.get('cx')) cy = float(node.get('cy')) r = float(node.get('r')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" % ( cx + r, cy, r, r, cx, cy + r, r, r, cx - r, cy, r, r, cx, cy - r, r, r, cx + r, cy) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('ellipse', 'svg'): cx = float(node.get('cx')) cy = float(node.get('cy')) rx = float(node.get('rx')) ry = float(node.get('ry')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" % ( cx + rx, cy, rx, ry, cx, cy + ry, rx, ry, cx - rx, cy, rx, ry, cx, cy - ry, rx, ry, cx + rx, cy) p = cubicsuperpath.parsePath(d) elif (node.tag == inkex.addNS('polygon', 'svg')) or (node.tag == inkex.addNS( 'polyline', 'svg')): points = node.get('points') if not points: return points = points.strip().split(" ") points = map(lambda x: x.split(","), points) d = "M " for point in points: x = float(point[0]) y = float(point[1]) d = d + "%f,%f " % (x, y) #Close the loop if it is a ploygon if node.tag == inkex.addNS('polygon', 'svg'): d = d + "Z" p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('line', 'svg'): x1 = float(node.get('x1')) y1 = float(node.get('y1')) x2 = float(node.get('x2')) y2 = float(node.get('y2')) d = "M " d = "M %f,%f %f,%f" % (x1, y1, x2, y2) p = cubicsuperpath.parsePath(d) else: return trans = node.get('transform') if trans: mat = simpletransform.composeTransform( mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, p) ################################################### ## Break Curves down into small lines ################################################### f = self.flatness is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, f) is_flat = 1 except IndexError: break except: f += 0.1 if f > 2: break #something has gone very wrong. ################################################### for sub in p: for i in range(len(sub) - 1): x1 = sub[i][1][0] y1 = sub[i][1][1] x2 = sub[i + 1][1][0] y2 = sub[i + 1][1][1] self.lines.append([x1, y1, x2, y2, rgb, path_id])
def effect(self): setup = self.options.setup #inkex.debug(setup) pathNodes = self.document.xpath('//svg:line', namespaces=inkex.NSS) for cPathNode in pathNodes: cPathNode.getparent().remove(cPathNode) for id, node in self.selected.iteritems(): #inkex.debug(node.get('id')) node.set('transform', 'translate(0,0)') #29.03.20 if node.tag == inkex.addNS('path', 'svg'): first = True gcode = ("M3 S255\nG90\n") #+"G01 F500.000\n" d = node.get('d') p = cubicsuperpath.parsePath(d) #subdivide dots points in .1 parts cspsubdiv.cspsubdiv(p, .1) #find low y value cp = [] g = 0 h = 0 #------------------------------------------- c = p[0][0][0][0] for csp in p[0]: b = csp[0][0] if (b < c): c = b f = p[0][0][0][1] for csp in p[0]: e = csp[0][1] if (e < f): f = e h = g g += 1 for csp in p[0]: b = csp[0][0] - c e = csp[0][1] - f cp.append([[b + 10, e + 10]]) #............................................................ np = [] Lfirst = cp[0:h] Lsecond = cp[h:] np = Lsecond + Lfirst np1 = [] for csp in np: cmd = 'L' x = str(round(self.uutounit(csp[0][0], "mm"), 2)) y = str(round(self.uutounit(csp[0][1], "mm"), 2)) if first: cmd = 'M' first = False line1 = inkex.etree.SubElement( self.current_layer, inkex.addNS('line', 'svg'), { 'id': 'costy', 'x1': '0', 'y1': '0', 'style': 'stroke-width:1;stroke:red', 'x2': x, 'y2': y }) gcode1 = "G01 X" + x + " Y" + y + "\n" gcode += gcode1 #line1 = inkex.etree.SubElement(self.current_layer, inkex.addNS('line','svg'), {'id': 'costy1','x1': '0', 'y0': '0', 'style': 'stroke-width:1;stroke:red', 'x2': x, 'y2': y} ) np1.append([cmd, [csp[0][0], csp[0][1]]]) gcode += "G01 X" + x + " Y" + y + "\n" #gcode += "G01 X" + x + " Y" + y + "\n" node.set('d', simplepath.formatPath(np1)) ''' inkex.debug(np1) ''' gcode += gcode1 gcode += "G01 X0 Y0\n" f = open("costycnc.nc", 'w') f.write(str(gcode)) f.close()
def process_shape(self, node, mat): nodetype = node.get(inkex.addNS("type","sodipodi")) if nodetype == "arc": # These are actually only used for checking the maths ui_arc = True ui_cx = float(node.get(inkex.addNS('cx','sodipodi'))) ui_cy = float(node.get(inkex.addNS('cy','sodipodi'))) ui_r = float(node.get(inkex.addNS('r','sodipodi'),0.0)) ui_rx = float(node.get(inkex.addNS('rx','sodipodi'),ui_r)) ui_ry = float(node.get(inkex.addNS('ry','sodipodi'),ui_r)) ui_a0 = float(node.get(inkex.addNS('start','sodipodi'),0)) ui_a1 = float(node.get(inkex.addNS('end','sodipodi'),2*math.pi)) else: ui_arc = False rgb = (0,0,0) style = node.get('style') if style: style = simplestyle.parseStyle(style) if style.has_key('stroke'): if style['stroke'] and style['stroke'] != 'none' and style['stroke'][0:3] != 'url': rgb = simplestyle.parseColor(style['stroke']) hsl = coloreffect.ColorEffect.rgb_to_hsl(coloreffect.ColorEffect(),rgb[0]/255.0,rgb[1]/255.0,rgb[2]/255.0) self.closed = 0 # only for LWPOLYLINE self.color = 7 # default is black if hsl[2]: self.color = 1 + (int(6*hsl[0] + 0.5) % 6) # use 6 hues trans = node.get('transform') if trans: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) if node.tag == inkex.addNS('path','svg'): d = node.get('d') if not d: inkex.errormsg("PATH DATA MISSING!") inkex.sys.exit() return # Filter out any eliptical arcs for special treatment: simplep = simplepath.parsePath(d) split = split_arc_nonarc(simplep) arc_simplep = split[1] simplep = split[0] if len(simplep)>0: if (simplep[-1][0] == 'z' or simplep[-1][0] == 'Z'): self.closed = 1 p = cubicsuperpath.CubicSuperPath(simplep) if (self.options.FLATTENBES): cspsubdiv.cspsubdiv(p, self.options.flat) np = [] for sp in p: first = True for csp in sp: cmd = 'L' if first: cmd = 'M' first = False np.append([cmd,[csp[1][0],csp[1][1]]]) p = cubicsuperpath.parsePath(simplepath.formatPath(np)) simpletransform.applyTransformToPath(mat, p) for sub in p: for i in range(len(sub)-1): s = sub[i] e = sub[i+1] if s[1] == s[2] and e[0] == e[1]: if (self.options.POLY == 'true'): self.LWPOLY_line([s[1],e[1]]) else: self.dxf_line([s[1],e[1]]) elif (self.options.ROBO == 'true'): self.ROBO_spline([s[1],s[2],e[0],e[1]]) else: self.dxf_spline([s[1],s[2],e[0],e[1]]) # Now process any arc segments: if len(arc_simplep) > 0: # As our path is broken by arcs, we cannot have a closed polyline: self.closed = 0 i = 0 while i < len(arc_simplep): cmd, params = arc_simplep[i] if cmd == 'M': p0 = params[:] else: p1 = params[-2:] rx,ry,theta,largearc,sweep = params[0:5] e_params = convert_arc_abrxry0_to_crxry00102(p0,p1,rx,ry,theta,largearc==1,sweep==1) cx,cy = e_params[0] if (i<len(arc_simplep)-1): cmd2, params2 = arc_simplep[i+1] else: cmd2 = '-' if cmd2 == 'A' and params2[0:5] == params[0:5] and params2[-2:] == p0: # complete circle or ellipse a0 = 0 a1 = 2.0*math.pi i = i + 1 p1 = p0 else: a0 = e_params[4] a1 = e_params[5] p0 = p1 self.dxf_arc_transform(mat,cx,cy,rx,ry,theta,a0,a1) # check did we get our maths right? if ui_arc and ((abs(cx - ui_cx) > 0.05) or (abs(cy - ui_cy) > 0.05) or (abs(a0 - ui_a0)>0.1) or (abs(a1 - ui_a1)>0.1)): inkex.errormsg("WARNING, Maths failure. Stored attributes of arc and calculated values do not agree!:") inkex.errormsg("sodipodi:\tc=[%f,%f],r=[%f,%f],a0=%fpi,a1=%fpi" % (ui_cx,ui_cy,ui_rx,ui_ry,ui_a0/math.pi,ui_a1/math.pi)) inkex.errormsg("raw:\tc=[%f,%f],r=[%f,%f],a0=%fpi,a1=%fpi" % (cx,cy,rx,ry,a0/math.pi,a1/math.pi)) i = i+1 return elif node.tag in [ inkex.addNS('circle','svg'), 'circle', \ inkex.addNS('ellipse','svg'), 'ellipse' ]: cx = float(node.get('cx',0)) cy = float(node.get('cy',0)) if node.tag == inkex.addNS('circle','svg'): rx = float(node.get('r',0)) ry = rx else: rx = float(node.get('rx',0)) ry = float(node.get('ry',rx)) a0 = 0.0 a1 = 2*math.pi self.dxf_arc_transform(mat,cx,cy,rx,ry,0,a0,a1) return elif node.tag == inkex.addNS('rect','svg'): self.closed = 1 x = float(node.get('x')) y = float(node.get('y')) width = float(node.get('width')) height = float(node.get('height')) pt0 = [x,y] pt1 = [x + width, y] pt2 = [x + width, y + height] pt3 = [x, y + height] simpletransform.applyTransformToPoint(mat,pt0) simpletransform.applyTransformToPoint(mat,pt1) simpletransform.applyTransformToPoint(mat,pt2) simpletransform.applyTransformToPoint(mat,pt3) if (self.options.POLY == 'true'): self.LWPOLY_line([pt0,pt1]) self.LWPOLY_line([pt1,pt2]) self.LWPOLY_line([pt2,pt3]) self.LWPOLY_line([pt3,pt0]) else: self.dxf_line([pt0,pt1]) self.dxf_line([pt1,pt2]) self.dxf_line([pt2,pt3]) self.dxf_line([pt3,pt0]) return else: return
def process_shape(self, node, mat, group_stroke = None): ################################# ### Determine the shape type ### ################################# try: i = node.tag.find('}') if i >= 0: tag_type = node.tag[i+1:] except: tag_type="" ############################################## ### Set a unique identifier for each shape ### ############################################## self.id_cnt=self.id_cnt+1 path_id = "ID%d"%(self.id_cnt) sw_flag = False changed = False ####################################### ### Handle references to CSS data ### ####################################### class_val = node.get('class') if class_val: css_data = "" for cv in class_val.split(' '): if css_data!="": css_data = self.CSS_values.get_css_value(tag_type,cv)+";"+css_data else: css_data = self.CSS_values.get_css_value(tag_type,cv) # Remove the reference to the CSS data del node.attrib['class'] # Check if a style entry already exists. If it does # append the the existing style data to the CSS data # otherwise create a new style entry. if node.get('style'): if css_data!="": css_data = css_data + ";" + node.get('style') node.set('style', css_data) else: node.set('style', css_data) style = node.get('style') self.Cut_Type[path_id]="raster" # Set default type to raster text_message_warning = "SVG File with Color Coded Text Outlines Found: (i.e. Blue: engrave/ Red: cut)" line1 = "SVG File with color coded text outlines found (i.e. Blue: engrave/ Red: cut)." line2 = "Automatic conversion to paths failed: Try upgrading to Inkscape .90 or later" line3 = "To convert manually in Inkscape: select the text then select \"Path\"-\"Object to Path\" in the menu bar." text_message_fatal = "%s\n\n%s\n\n%s" %(line1,line2,line3) ############################################## ### Handle 'style' data outside of style ### ############################################## stroke_outside = node.get('stroke') if not stroke_outside: stroke_outside = group_stroke if stroke_outside: stroke_width_outside = node.get('stroke-width') col = stroke_outside col= col.strip() if simplestyle.isColor(col): c=simplestyle.parseColor(col) (new_val,changed,k40_action)=self.colmod(c[0],c[1],c[2],path_id) else: new_val = col if changed: node.set('stroke',new_val) node.set('stroke-width',"0.0") node.set('k40_action', k40_action) sw_flag = True if sw_flag == True: if node.tag == inkex.addNS('text','svg') or node.tag == inkex.addNS('flowRoot','svg'): if (self.txt2paths==False): raise SVG_TEXT_EXCEPTION(text_message_warning) else: raise Exception(text_message_fatal) ################################################### ### Handle 'k40_action' data outside of style ### ################################################### if node.get('k40_action'): k40_action = node.get('k40_action') changed=True self.Cut_Type[path_id]=k40_action ############################################## ### Handle 'style' data ### ############################################## if style: declarations = style.split(';') i_sw = -1 sw_prop = 'stroke-width' for i,decl in enumerate(declarations): parts = decl.split(':', 2) if len(parts) == 2: (prop, col) = parts prop = prop.strip().lower() if prop == 'k40_action': changed = True self.Cut_Type[path_id]=col #if prop in color_props: if prop == sw_prop: i_sw = i if prop == 'stroke': col= col.strip() if simplestyle.isColor(col): c=simplestyle.parseColor(col) (new_val,changed,k40_action)=self.colmod(c[0],c[1],c[2],path_id) else: new_val = col if changed: declarations[i] = prop + ':' + new_val declarations.append('k40_action' + ':' + k40_action) sw_flag = True if sw_flag == True: if node.tag == inkex.addNS('text','svg') or node.tag == inkex.addNS('flowRoot','svg'): if (self.txt2paths==False): raise SVG_TEXT_EXCEPTION(text_message_warning) else: raise Exception(text_message_fatal) if i_sw != -1: declarations[i_sw] = sw_prop + ':' + "0.0" else: declarations.append(sw_prop + ':' + "0.0") node.set('style', ';'.join(declarations)) ############################################## ##################################################### ### If vector data was found save the path data ### ##################################################### if changed: if node.tag == inkex.addNS('path','svg'): d = node.get('d') if not d: return p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('rect','svg'): x = float(node.get('x')) y = float(node.get('y')) width = float(node.get('width')) height = float(node.get('height')) rx = 0.0 ry = 0.0 if node.get('rx'): rx=float(node.get('rx')) if node.get('ry'): ry=float(node.get('ry')) if max(rx,ry) > 0.0: if rx==0.0 or ry==0.0: rx = max(rx,ry) ry = rx Rxmax = abs(width)/2.0 Rymax = abs(height)/2.0 rx = min(rx,Rxmax) ry = min(ry,Rymax) L1 = "M %f,%f %f,%f " %(x+rx , y , x+width-rx , y ) C1 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width , y+ry ) L2 = "M %f,%f %f,%f " %(x+width , y+ry , x+width , y+height-ry) C2 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+width-rx , y+height ) L3 = "M %f,%f %f,%f " %(x+width-rx , y+height , x+rx , y+height ) C3 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x , y+height-ry) L4 = "M %f,%f %f,%f " %(x , y+height-ry, x , y+ry ) C4 = "A %f,%f 0 0 1 %f,%f" %(rx , ry , x+rx , y ) d = L1 + C1 + L2 + C2 + L3 + C3 + L4 + C4 else: d = "M %f,%f %f,%f %f,%f %f,%f Z" %(x,y, x+width,y, x+width,y+height, x,y+height) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('circle','svg'): cx = float(node.get('cx') ) cy = float(node.get('cy')) r = float(node.get('r')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" %(cx+r,cy, r,r,cx,cy+r, r,r,cx-r,cy, r,r,cx,cy-r, r,r,cx+r,cy) p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('ellipse','svg'): cx = float(node.get('cx')) cy = float(node.get('cy')) if node.get('r'): r = float(node.get('r')) rx = r ry = r if node.get('rx'): rx = float(node.get('rx')) if node.get('ry'): ry = float(node.get('ry')) d = "M %f,%f A %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f %f,%f 0 0 1 %f,%f Z" %(cx+rx,cy, rx,ry,cx,cy+ry, rx,ry,cx-rx,cy, rx,ry,cx,cy-ry, rx,ry,cx+rx,cy) p = cubicsuperpath.parsePath(d) elif (node.tag == inkex.addNS('polygon','svg')) or (node.tag == inkex.addNS('polyline','svg')): points = node.get('points') if not points: return points = points.replace(',', ' ') while points.find(' ') > -1: points = points.replace(' ', ' ') points = points.strip().split(" ") d = "M " for i in range(0,len(points),2): x = float(points[i]) y = float(points[i+1]) d = d + "%f,%f " %(x,y) #Close the loop if it is a ploygon if node.tag == inkex.addNS('polygon','svg'): d = d + "Z" p = cubicsuperpath.parsePath(d) elif node.tag == inkex.addNS('line','svg'): x1 = float(node.get('x1')) y1 = float(node.get('y1')) x2 = float(node.get('x2')) y2 = float(node.get('y2')) d = "M " d = "M %f,%f %f,%f" %(x1,y1,x2,y2) p = cubicsuperpath.parsePath(d) else: #print("something was ignored") #print(node.tag) return trans = node.get('transform') if trans: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, p) ########################################## ## Break Curves down into small lines ### ########################################## f = self.flatness is_flat = 0 while is_flat < 1: try: cspsubdiv.cspsubdiv(p, f) is_flat = 1 except IndexError: break except: f += 0.1 if f>2 : break #something has gone very wrong. ########################################## rgb=(0,0,0) for sub in p: for i in range(len(sub)-1): x1 = sub[i][1][0] y1 = sub[i][1][1] x2 = sub[i+1][1][0] y2 = sub[i+1][1][1] self.lines.append([x1,y1,x2,y2,rgb,path_id])
def flatten_subpath(self, subpath): path = [deepcopy(subpath)] cspsubdiv(path, 0.1) return self.strip_control_points(path[0])
def laser(self): gcode = "" if (self.karyacnc): gcode = ";KARYACNC," + self.karyacnc + "\n" getstyles = ('fill:', 'stroke:', 'stroke-width:') def getStyles(node): res = { "fill:": "#ffffff", "stroke:": "#000000", "stroke-width:": "0", "deep:": 0, "repeat:": 0 } #if 'deep' in node.attrib: res['deep:'] = node.get('deep') res['repeat:'] = node.get('repeat') if 'style' in node.attrib: style = node.get( 'style' ) # fixme: this will break for presentation attributes! if style != '': #inkex.debug('old style:'+style) styles = style.split(';') for i in range(len(styles)): for st in getstyles: if styles[i].startswith(st): res[st] = styles[i][len(st):] return res if self.selected_paths == {}: paths = [] self.error( _("No paths are selected! Trying to work on all available paths." ), "warning") else: paths = self.selected_paths #self.check_dir() print_(("self.layers=", self.layers)) print_(("paths=", paths)) kpaths = [] xmin = 100000 ymin = 100000 for layer in self.layers: if layer in paths: print_(("layer", layer)) p = [] pc = [] flips = [] for path in paths[layer]: print_(str(layer)) if "d" not in path.keys(): self.error( _("Warning: One or more paths dont have 'd' parameter, try to Ungroup (Ctrl+Shift+G) and Object to Path (Ctrl+Shift+C)!" ), "selection_contains_objects_that_are_not_paths") continue d = path.get('d') pstyle = getStyles(path) col = pstyle["fill:"] csp1 = cubicsuperpath.parsePath(d) #new.get('d')) csp1 = self.apply_transforms(path, csp1) #Ryan modification # flatten if contain BICUBIC or ARC if (d.find("A") >= 0 or d.find("C") >= 0 or d.find("Q") >= 0 or d.find("a") >= 0 or d.find("c") >= 0 or d.find("q") >= 0): cspsubdiv.cspsubdiv(csp1, self.options.flatten * 0.5) np = [] for sp in csp1: first = True num = len(sp) #gcode+=";"+str(cw)+"\n" sum = 0 ln = 0 kpath = [] for icsp in range(num): csp = sp[icsp] kpath.append((csp[1][0], csp[1][1])) xmin = min(xmin, csp[1][0]) ymin = min(ymin, csp[1][1]) kpaths.append((pstyle, kpath)) self.export_path(kpaths, xmin, ymin)
def laser(self) : def get_boundaries(points): minx,miny,maxx,maxy=None,None,None,None out=[[],[],[],[]] for p in points: if minx==p[0]: out[0]+=[p] if minx==None or p[0]<minx: minx=p[0] out[0]=[p] if miny==p[1]: out[1]+=[p] if miny==None or p[1]<miny: miny=p[1] out[1]=[p] if maxx==p[0]: out[2]+=[p] if maxx==None or p[0]>maxx: maxx=p[0] out[2]=[p] if maxy==p[1]: out[3]+=[p] if maxy==None or p[1]>maxy: maxy=p[1] out[3]=[p] return out gcode="" if (self.karyacnc):gcode = ";KARYACNC,"+self.karyacnc+"\n" getstyles=('fill:','stroke:','stroke-width:') def getStyles(node): res={"fill:":"#ffffff","stroke:":"#000000","stroke-width:":"0","deep:":0,"repeat:":0} #if 'deep' in node.attrib: res['deep:']=node.get('deep') res['repeat:']=node.get('repeat') if 'style' in node.attrib: style=node.get('style') # fixme: this will break for presentation attributes! if style!='': #inkex.debug('old style:'+style) styles=style.split(';') for i in range(len(styles)): for st in getstyles: if styles[i].startswith(st): res[st]=styles[i][len(st):] return res if self.selected_paths == {} : paths=[] self.error(_("No paths are selected! Trying to work on all available paths."),"warning") else : paths = self.selected_paths self.check_dir() print_(("self.layers=",self.layers)) print_(("paths=",paths)) for layer in self.layers : if layer in paths : print_(("layer",layer)) p = [] pc= [] flips=[] for path in paths[layer] : print_(str(layer)) if "d" not in path.keys() : self.error(_("Warning: One or more paths dont have 'd' parameter, try to Ungroup (Ctrl+Shift+G) and Object to Path (Ctrl+Shift+C)!"),"selection_contains_objects_that_are_not_paths") continue d = path.get('d') pstyle=getStyles(path) col=pstyle["fill:"] csp1 = cubicsuperpath.parsePath(d)#new.get('d')) csp1 = self.apply_transforms(path, csp1) #Ryan modification # flatten if contain BICUBIC or ARC if (d.find("A")>=0 or d.find("C")>=0 or d.find("Q")>=0 or d.find("a")>=0 or d.find("c")>=0 or d.find("q")>=0): cspsubdiv.cspsubdiv(csp1, self.options.flatten*0.5) np = [] # need to check if its clockwise yellow=col=="#ffff00" dyellow=col=="#808000" outer=not yellow def isClockwise(poly): sum = 0; for i in range(len(poly)): cur = poly[i][1] ii=i + 1 if ii==len(poly):ii=0; next = poly[ii][1] #sum += (next[1] * cur[0]) - (next[0] * cur[1]) sum += (next[0] - cur[0]) * (next[1] + cur[1]) return sum; clockw=[] for sp in csp1: first = True num=len(sp) #gcode+=";"+str(cw)+"\n" sum=0 ln=0 for icsp in range(num): csp=sp[icsp] icsp2=icsp+1 if icsp2==num:icsp2=0 csp2=sp[icsp2] cmd = 'L' if first: cmd = 'M' first = False np.append([cmd,[csp[1][0],csp[1][1]]]) # y2 * x1 - x2 * y1 #sum += (csp2[1][1] * csp[1][0]) - (csp2[1][0] * csp[1][1]) # x2 - x1 * x2 * y1 sum += (csp2[1][0] - csp[1][0]) * (csp2[1][1] + csp[1][1]) ln = ln + vector_from_to_length(csp2[1],csp[1]) #np.insert(0,[cmd,[csp[1][0],csp[1][1]]]) flip=sum<=0 if yellow:flip=not flip clockw.append(flip) if ln<4:flip=False #if outer:flip=flip if yellow or dyellow:flips.append(flip) pc.append(pstyle) outer=False # check inner or outside here def isInside(point, vs): # ray-casting algorithm based on # http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html x = point[0] y = point[1] inside = False j=len(vs)-1 for i in range(len(vs)): xi = vs[i][1][0] yi = vs[i][1][1] xj = vs[j][1][0] yj = vs[j][1][1] intersect = ((yi > y) != (yj > y)) and (x < (xj - xi) * (y - yi) / (yj - yi) + xi) if intersect: inside = not inside j=i return inside if not (yellow or dyellow): for i in range(len(csp1)): cflip=True for j in range(len(csp1)): if (i!=j): spi=csp1[i] spj=csp1[j] # check every point in spj is inside spi flip=False for k in range(len(spi)): csp=spi[k] if isInside([csp[1][0],csp[1][1]],spj): flip=not flip break if flip:cflip=not cflip if not clockw[i]:cflip=not cflip flips.append(cflip) #flips[len(flips)-1]=not outer #node.set('d',simplepath.formatPath(np)) #print(simplepath.formatPath(np)) #gcode+=";"+simplepath.formatPath(np) csp=cubicsuperpath.parsePath(simplepath.formatPath(np)) # ================ p+=csp curve = self.parse_curve(p, layer,flips,pc) gcode += self.generate_gcode(curve, layer, 0,pc,flips) self.export_gcode(gcode)