def drawCircles(self, hole_diameter, diameter): # Attributes for the center hole, then create it, if diameter is 0, dont # create it circle_elements = [] attributes = { 'style': simplestyle.formatStyle({'stroke': 'none', 'fill': 'black'}), 'r': str(hole_diameter / 2) } if self.options.hole_diameter > 0: circle_elements.append(attributes) # Attributes for the guide hole in the center hole, then create it attributes = { 'style': simplestyle.formatStyle( {'stroke': 'white', 'fill': 'white', 'stroke-width': '0.1'}), 'r': '1' } circle_elements.append(attributes) # Attributes for the outer rim, then create it attributes = { 'style': simplestyle.formatStyle( {'stroke': 'black', 'stroke-width': '1', 'fill': 'none'}), 'r': str(diameter / 2) } if self.options.diameter > 0: circle_elements.append(attributes) return circle_elements
def do_entity(): global style, layer if block != defs: # in a BLOCK layer = block elif vals[groups['8']]: # use Common Layer Name layer = layer_nodes[vals[groups['8']][0]] color = '#000000' # default color if vals[groups['8']]: if layer_colors.has_key(vals[groups['8']][0]): if colors.has_key(layer_colors[vals[groups['8']][0]]): color = colors[layer_colors[vals[groups['8']][0]]] if vals[groups['62']]: # Common Color Number if colors.has_key(vals[groups['62']][0]): color = colors[vals[groups['62']][0]] style = simplestyle.formatStyle({'stroke': '%s' % color, 'fill': 'none'}) w = 0.5 # default lineweight for POINT if vals[groups['370']]: # Common Lineweight if vals[groups['370']][0] > 0: w = 90.0/25.4*vals[groups['370']][0]/100.0 if w < 0.5: w = 0.5 style = simplestyle.formatStyle({'stroke': '%s' % color, 'fill': 'none', 'stroke-width': '%.1f' % w}) if vals[groups['6']]: # Common Linetype if linetypes.has_key(vals[groups['6']][0]): style += ';' + linetypes[vals[groups['6']][0]] entities[entity]()
def write_month_header(self, g, m): txt_atts = {'style': simplestyle.formatStyle(self.style_month), 'x': str((self.month_w - self.day_w) / 2), 'y': str(self.day_h / 5 )} try: inkex.etree.SubElement(g, 'text', txt_atts).text = unicode( self.options.month_names[m-1], self.options.input_encode) except: inkex.errormsg(_('You must select a correct system encoding.')) exit(1) gw = inkex.etree.SubElement(g, 'g') week_x = 0 if self.options.start_day=='sun': day_names = self.options.day_names[:] else: day_names = self.options.day_names[1:] day_names.append(self.options.day_names[0]) if self.options.show_weeknr: day_names.insert(0, self.options.weeknr_name) for wday in day_names: txt_atts = {'style': simplestyle.formatStyle(self.style_day_name), 'x': str( self.day_w * week_x ), 'y': str( self.day_h ) } try: inkex.etree.SubElement(gw, 'text', txt_atts).text = unicode( wday, self.options.input_encode) except: inkex.errormsg(_('You must select a correct system encoding.')) exit(1) week_x += 1
def make_double_line(self, length): opt = self.options w1 = float(opt.stroke_width_1) w2 = float(opt.stroke_width_2) offset = 0.5*(w1 + w2) line = inkex.etree.Element('g') style_line1 = { 'fill': 'none', 'stroke': simplestyle.svgcolors[opt.stroke_color_1], 'stroke-width': opt.stroke_width_1+'px',} path_atts_1 = { inkex.addNS('connector-curvature', 'inkscape'): "0", 'd': "M 0.0,0.0 %f,0.0" % (length,), 'style': simplestyle.formatStyle(style_line1), } inkex.etree.SubElement(line, 'path', path_atts_1) style_line2 = { 'fill': 'none', 'stroke': simplestyle.svgcolors[opt.stroke_color_2], 'stroke-width': opt.stroke_width_2+'px',} path_atts_2 = { inkex.addNS('connector-curvature', 'inkscape'): "0", 'd': "M 0.0,%f %f,%f.0" % (offset, length, offset), 'style': simplestyle.formatStyle(style_line2),} inkex.etree.SubElement(line, 'path', path_atts_2) return line
def effect(self): defs = self.xpathSingle('/svg//defs') if not defs: defs = self.document.createElement('svg:defs') self.document.documentElement.appendChile(defs) for id, node in self.selected.iteritems(): mprops = ['marker', 'marker-start', 'marker-mid', 'marker-end'] try: style = simplestyle.parseStyle( node.attributes.getNamedItem('style').value) except: inkex.debug("No style attribute found for id: %s" % id) continue stroke = style.get('stroke', '#000000') for mprop in mprops: if style.has_key(mprop) and style[mprop] != 'none' and style[ mprop][:5] == 'url(#': marker_id = style[mprop][5:-1] try: old_mnode = self.xpathSingle( '/svg//marker[@id="%s"]' % marker_id) if not self.options.modify: mnode = old_mnode.cloneNode(True) else: mnode = old_mnode except: inkex.debug("unable to locate marker: %s" % marker_id) continue new_id = self.uniqueId(marker_id, not self.options.modify) style[mprop] = "url(#%s)" % new_id mnode.attributes.getNamedItem('id').value = new_id mnode.attributes.getNamedItemNS(inkex.NSS['inkscape'], 'stockid').value = new_id defs.appendChild(mnode) children = inkex.xml.xpath.Evaluate( '/svg//marker[@id="%s"]//*[@style]' % new_id, self.document, context=self.ctx) for child in children: cstyle = simplestyle.parseStyle( child.attributes.getNamedItem('style').value) if ('stroke' in cstyle and cstyle['stroke'] != 'none' ) or 'stroke' not in cstyle: cstyle['stroke'] = stroke if ('fill' in cstyle and cstyle['fill'] != 'none' ) or 'fill' not in cstyle: cstyle['fill'] = stroke child.attributes.getNamedItem( 'style').value = simplestyle.formatStyle(cstyle) node.attributes.getNamedItem( 'style').value = simplestyle.formatStyle(style)
def effect(self): for id, node in self.selected.iteritems(): if node.tag == '{http://www.w3.org/2000/svg}path': path=node break else: sys.stderr.write('Need one path selected\n') return pts = cubicsuperpath.parsePath(path.get('d')) if 'transform' in path.keys(): trans = path.get('transform') trans = simpletransform.parseTransform(trans) simpletransform.applyTransformToPath(trans, pts[i]) gtext = inkex.etree.SubElement(path.xpath('..')[0], inkex.addNS('g','svg'), {} ) gdots = inkex.etree.SubElement(path.xpath('..')[0], inkex.addNS('g','svg'), {} ) size = 10 if 'style' in path.attrib: style=path.get('style') if style!='': styles=style.split(';') for i in range(len(styles)): if styles[i].startswith('stroke-width'): if ( styles[i].endswith('px') or styles[i].endswith('cm') ) : size=float(styles[i][len('stroke-width:'):-2])*2 else: size=float(styles[i][len('stroke-width:'):])*2 # if len(pts[0])>2: # size = math.sqrt(math.pow(pts[0][0][0][0]-pts[0][1][0][0],2)+math.pow(pts[0][0][0][1]-pts[0][1][0][1],2))/10 it = 0 for sub in pts: for p in sub: if it == 0: style = { 'stroke': 'none', 'fill': 'black' } x0 = p[0][0] y0 = p[0][1] circ_attribs = {'id':'pt0','style':simplestyle.formatStyle(style),'cx':str(x0), 'cy':str(y0),'r':str(size)} circle = inkex.etree.SubElement(gdots, inkex.addNS('circle','svg'), circ_attribs ) else: clone_attribs = { 'x':'0', 'y':'0', 'transform':'translate(%f,%f)' % (p[0][0]-x0,p[0][1]-y0) } clone = inkex.etree.SubElement(gdots, inkex.addNS('use','svg'), clone_attribs ) xlink = inkex.addNS('href','xlink') clone.set(xlink, '#pt0') text_style = { 'font-size':'%dpx' % (size*2.4), 'fill':'black', 'font-family':'DejaVu Sans', 'text-anchor':'middle' } text_attribs = { 'x':str(p[0][0]), 'y':str(p[0][1]-size*1.8), 'style':simplestyle.formatStyle(text_style) } text = inkex.etree.SubElement(gtext, inkex.addNS('text','svg'), text_attribs) tspan = inkex.etree.SubElement(text , 'tspan', {inkex.addNS('role','sodipodi'): 'line'}) tspan.text = '%d' % ( it+1 ) it+=1
def export_HATCH(): # mandatory group codes : (10, 20, 70, 72, 92, 93) (x, y, fill, Edge Type, Path Type, Number of edges) if vals[groups['10']] and vals[groups['20']] and vals[groups['70']] and vals[groups['72']] and vals[groups['92']] and vals[groups['93']]: if len(vals[groups['10']]) > 1 and len(vals[groups['20']]) == len(vals[groups['10']]): # optional group codes : (11, 21, 40, 50, 51, 73) (x, y, r, angle1, angle2, CCW) i10 = 1 # count start points i11 = 0 # count line end points i40 = 0 # count circles i72 = 0 # count edge type flags path = '' for i in range (0, len(vals[groups['93']])): xc = vals[groups['10']][i10] yc = vals[groups['20']][i10] if vals[groups['72']][i72] == 2: # arc rm = scale*vals[groups['40']][i40] a1 = vals[groups['50']][i40] path += 'M %f,%f ' % (xc + rm*math.cos(a1*math.pi/180.0), yc + rm*math.sin(a1*math.pi/180.0)) else: a1 = 0 path += 'M %f,%f ' % (xc, yc) for j in range(0, vals[groups['93']][i]): if vals[groups['92']][i] & 2: # polyline if j > 0: path += 'L %f,%f ' % (vals[groups['10']][i10], vals[groups['20']][i10]) if j == vals[groups['93']][i] - 1: i72 += 1 elif vals[groups['72']][i72] == 2: # arc xc = vals[groups['10']][i10] yc = vals[groups['20']][i10] rm = scale*vals[groups['40']][i40] a2 = vals[groups['51']][i40] diff = (a2 - a1 + 360) % (360) sweep = 1 - vals[groups['73']][i40] # sweep CCW large = 0 # large-arc-flag if diff: path += 'A %f,%f 0.0 %d %d %f,%f ' % (rm, rm, large, sweep, xc + rm*math.cos(a2*math.pi/180.0), yc + rm*math.sin(a2*math.pi/180.0)) else: path += 'A %f,%f 0.0 %d %d %f,%f ' % (rm, rm, large, sweep, xc + rm*math.cos((a1+180.0)*math.pi/180.0), yc + rm*math.sin((a1+180.0)*math.pi/180.0)) path += 'A %f,%f 0.0 %d %d %f,%f ' % (rm, rm, large, sweep, xc + rm*math.cos(a1*math.pi/180.0), yc + rm*math.sin(a1*math.pi/180.0)) i40 += 1 i72 += 1 elif vals[groups['72']][i72] == 1: # line path += 'L %f,%f ' % (scale*(extrude*vals[groups['11']][i11] - xmin), height - scale*(vals[groups['21']][i11] - ymin)) i11 += 1 i72 += 1 i10 += 1 path += "z " if vals[groups['70']][0]: style = simplestyle.formatStyle({'fill': '%s' % color}) else: style = simplestyle.formatStyle({'fill': 'url(#Hatch)', 'fill-opacity': '1.0'}) attribs = {'d': path, 'style': style} inkex.etree.SubElement(layer, 'path', attribs)
def effect(self): self.checkopts() o = self.options.fbedges oNF,oBF,oNL,oBL = o,o,o,o if self.doMultiScale: strings, meta = ffproc.FindStringsMultiScale(self.options.strings,self.options.firstscalelength, self.options.lastscalelength,self.options.nutwidth,self.options.bridgewidth, self.options.perpdist,oNF,oBF,oNL,oBL) else: strings, meta = ffproc.FindStringsSingleScale(self.options.strings,self.options.scalelength, self.options.nutwidth,self.options.bridgewidth, oNF,oBF,oNL,oBL) frets = ffproc.FindFrets(strings, meta, self.scale, self.tuning, self.options.frets) edgepath = seg2path(meta[0]) + seg2path(meta[-1]) stringpath = "".join([seg2path(s) for s in strings]) fretpath = "".join(["".join([seg2path(f) for f in s]) for s in frets]) group = self.document.createElement('svg:g') group.setAttribute('transform',"scale(%s,%s)" % (self.options.pxperunit,self.options.pxperunit)) self.document.documentElement.appendChild(group) edge = self.document.createElement('svg:path') s = {'stroke-linejoin': 'miter', 'stroke-width': '0.01px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#0000FF', 'stroke-linecap': 'butt', 'fill': 'none'} edge.setAttribute('style', simplestyle.formatStyle(s)) edge.setAttribute('d', edgepath) string = self.document.createElement('svg:path') s = {'stroke-linejoin': 'miter', 'stroke-width': '0.01px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#FF0000', 'stroke-linecap': 'butt', 'fill': 'none'} string.setAttribute('style', simplestyle.formatStyle(s)) string.setAttribute('d', stringpath) fret = self.document.createElement('svg:path') s = {'stroke-linejoin': 'miter', 'stroke-width': '0.01px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#000000', 'stroke-linecap': 'butt', 'fill': 'none'} fret.setAttribute('style', simplestyle.formatStyle(s)) fret.setAttribute('d', fretpath) group.appendChild(edge) group.appendChild(string) group.appendChild(fret)
def effect(self): """ Effect behaviour. Overrides base class' method and draws something. """ # color self.options.dotFill = self.getColorString(self.options.dotFill) # constants self.dotStyle = simplestyle.formatStyle({'fill': self.options.dotFill,'stroke':'none'}) self.scale = self.getUnittouu("1" + self.options.units) self.dotR = str(self.options.dotSize * (self.scale/2)) self.computations(radians(self.options.angleOnFootside)) # processing variables self.generatedCircles = [] self.gridContainer = self.current_layer self.generate() if self.options.variant == 'rectangle': self.removeGroups(1, 2) elif self.options.variant == 'hexagon1': self.removeGroups(0, 3) elif self.options.variant == 'hexagon2' or self.options.variant == 'snow2': for i in range(0, len(self.generatedCircles), 1): self.removeDots(i, (((i%2)+1)*2)%3, 3) elif self.options.variant == 'hexagon3': for i in range(0, len(self.generatedCircles), 2): self.removeDots(i, (i//2+1)%2, 2) elif self.options.variant == 'hexagon4': self.removeGroups(0, 4) elif self.options.variant == 'hexagon5' or self.options.variant == 'snow1': for i in range(0, len(self.generatedCircles), 2): self.removeDots(i, 1, 2) self.dotStyle = simplestyle.formatStyle({'fill': 'none','stroke':self.options.dotFill,'stroke-width':0.7}) self.dotR = str((((self.options.innerDiameter * pi) / self.options.dotsPerCircle) / 2) * self.scale) self.generatedCircles = [] if self.options.variant == 'snow2': self.options.dotsPerCircle = self.options.dotsPerCircle // 3 self.computations(radians(self.options.angleOnFootside)) self.generate() elif self.options.variant == 'snow1': self.generate() self.removeGroups(1, 2) for i in range(0, len(self.generatedCircles), 2): self.removeDots(i, i%4, 2) for i in range(0, len(self.generatedCircles), 2): self.removeDots(i, (i+1)%2, 2) for i in range(2, len(self.generatedCircles), 4): self.removeDots(i, 0, self.options.dotsPerCircle)
def _merge_style(self, node, style): """Propagate style and transform to remove inheritance Originally from https://github.com/nikitakit/svg2sif/blob/master/synfig_prepare.py#L370 """ # Compose the style attribs this_style = simplestyle.parseStyle(node.get("style", "")) remaining_style = {} # Style attributes that are not propagated # Filters should remain on the top ancestor non_propagated = ["filter"] for key in non_propagated: if key in this_style.keys(): remaining_style[key] = this_style[key] del this_style[key] # Create a copy of the parent style, and merge this style into it parent_style_copy = style.copy() parent_style_copy.update(this_style) this_style = parent_style_copy # Merge in any attributes outside of the style style_attribs = ["fill", "stroke"] for attrib in style_attribs: if node.get(attrib): this_style[attrib] = node.get(attrib) del node.attrib[attrib] if (node.tag == addNS("svg", "svg") or node.tag == addNS("g", "svg") or node.tag == addNS("a", "svg") or node.tag == addNS("switch", "svg")): # Leave only non-propagating style attributes if len(remaining_style) == 0: if "style" in node.keys(): del node.attrib["style"] else: node.set("style", simplestyle.formatStyle(remaining_style)) else: # This element is not a container # Merge remaining_style into this_style this_style.update(remaining_style) # Set the element's style attribs node.set("style", simplestyle.formatStyle(this_style))
def addTextOnPath(self, node, x, y, text, id, anchor, startOffset, dy=0): new = inkex.etree.SubElement(node, inkex.addNS("textPath", "svg")) s = { "text-align": "center", "vertical-align": "bottom", "text-anchor": anchor, "font-size": str(self.options.fontsize), "fill-opacity": "1.0", "stroke": "none", "font-weight": "normal", "font-style": "normal", "fill": "#000000", } new.set("style", simplestyle.formatStyle(s)) new.set(inkex.addNS("href", "xlink"), "#" + id) new.set("startOffset", startOffset) new.set("dy", str(dy)) # dubious merit # new.append(tp) if text[-2:] == "^2": appendSuperScript(new, "2") new.text = str(text)[:-2] else: new.text = str(text) # node.set('transform','rotate(180,'+str(-x)+','+str(-y)+')') node.set("x", str(x)) node.set("y", str(y))
def createXAt(xp, coor): style = {'color':'#000000', 'fill':'none', 'stroke':'#000000', 'stroke-width':'1.1', 'stroke-linecap':'round'} path = 'M '+ str(coor[xp][0]) + ',' + str(coor[xp][1]) + ' m 4,4 '\ 'l -8,-8 M '+ str(coor[xp][0]) + ',' + str(coor[xp][1]) + ''\ 'm -4,4 l 8,-8' return {'d':path, 'style':simplestyle.formatStyle(style)}
def effect(self): svg = self.document.getroot() width = float(self.document.getroot().get('width')) height = float(self.document.getroot().get('height')) group = inkex.etree.SubElement(self.current_layer, 'g', { inkex.addNS('label', 'inkscape') : 'Slider electrodes' }) style = { 'stroke' : 'none', 'fill' : '#000000' } eWidth = width / self.options.count spikeWidth = 0.6 * eWidth for eid in range(self.options.count): if eid == 0: path = self.genPathString((eid * eWidth, 0, (eid + 1) * eWidth + 0.4 * spikeWidth, height), spikeWidth, first=True) elif eid == self.options.count - 1: path = self.genPathString((eid * eWidth - 0.4 * spikeWidth, 0, (eid + 1) * eWidth, height), spikeWidth, last=True) else: path = self.genPathString((eid * eWidth - 0.4 * spikeWidth, 0, (eid + 1) * eWidth + 0.4 * spikeWidth, height), spikeWidth) e = inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), { 'style' : simplestyle.formatStyle(style), 'd' : path })
def joinFillsWithNode(self, node, stroke_width, path): """ Generate a SVG <path> element containing the path data "path". Then put this new <path> element into a <group> with the supplied node. This means making a new <group> element and moving node under it with the new <path> as a sibling element. """ if (not path) or (len(path) == 0): return # Make a new SVG <group> element whose parent is the parent of node parent = node.getparent() # was: if not parent: if parent is None: parent = self.document.getroot() g = inkex.etree.SubElement(parent, inkex.addNS("g", "svg")) # Move node to be a child of this new <g> element g.append(node) # Now make a <path> element which contains the hatches & is a child # of the new <g> element style = {"stroke": "#000000", "fill": "none", "stroke-width": "%f" % stroke_width} line_attribs = {"style": simplestyle.formatStyle(style), "d": path} tran = node.get("transform") if (tran != None) and (tran != ""): line_attribs["transform"] = tran inkex.etree.SubElement(g, inkex.addNS("path", "svg"), line_attribs)
def createCapoPos(coor): textstyle = {'font-size': '8', 'font-family': 'Century Schoolbook L', 'text-anchor': 'end', 'fill': '#000000'} return { 'style':simplestyle.formatStyle(textstyle), 'x': str(coor[0]-5), 'y': str(coor[1]+4) }
def leftFingerNumberAt(fp, coor): textstyle = {'font-size': '8', 'font-family': 'Century Schoolbook L', 'text-anchor': 'start', 'fill': '#000000'} return { 'style':simplestyle.formatStyle(textstyle), 'x': str(coor[fp[0]][fp[1]][0]), 'y': str(coor[fp[0]][fp[1]][1]) }
def createHeader(coor): textstyle = {'font-size': '18', 'font-family': 'Linux Libertine O', 'text-anchor': 'middle', 'fill': '#000000'} return { 'style':simplestyle.formatStyle(textstyle), 'x': str(coor[0]), 'y': str(coor[1]) }
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): p = simplepath.parsePath(node.get('d')) a =[] pen = None subPathStart = None for cmd,params in p: if cmd == 'C': a.extend([['M', params[:2]], ['L', pen], ['M', params[2:4]], ['L', params[-2:]]]) if cmd == 'Q': a.extend([['M', params[:2]], ['L', pen], ['M', params[:2]], ['L', params[-2:]]]) if cmd == 'M': subPathStart = params if cmd == 'Z': pen = subPathStart else: pen = params[-2:] if len(a) > 0: s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#000000', 'stroke-linecap': 'butt', 'fill': 'none'} attribs = {'style':simplestyle.formatStyle(s),'d':simplepath.formatPath(a)} inkex.etree.SubElement(node.getparent(), inkex.addNS('path','svg'), attribs)
def effect(self): length = self.options.length spacing = self.options.spacing angle = radians(self.options.angle) # generate points: list of (x, y) pairs points = [] x = 0 tas = tan(angle) * spacing while x < length: # move along path, generating the next 'tooth' points.append((x, 0)) points.append((x + tas, spacing)) points.append((x + spacing, spacing)) points.append((x + spacing + tas, 0)) x += spacing * 2.0 path = points_to_svgd(points) # Embed gear in group to make animation easier: # Translate group, Rotate path. t = "translate(" + str(self.view_center[0]) + "," + str(self.view_center[1]) + ")" g_attribs = {inkex.addNS("label", "inkscape"): "RackGear" + str(length), "transform": t} g = inkex.etree.SubElement(self.current_layer, "g", g_attribs) # Create SVG Path for gear style = {"stroke": "#000000", "fill": "none"} gear_attribs = {"style": simplestyle.formatStyle(style), "d": path} gear = inkex.etree.SubElement(g, inkex.addNS("path", "svg"), gear_attribs)
def drawSegment(self, line_style, angle, segment_angle, outer_diameter, width): path = {'style': simplestyle.formatStyle(line_style)} path['d'] = '' outer_radius = outer_diameter / 2 # Go to the first point in the segment path['d'] += self.parsePathData( 'M', calculatePoint(angle, outer_radius - width)) # Go to the second point in the segment path['d'] += self.parsePathData('L', calculatePoint(angle, outer_radius)) # Go to the third point in the segment, draw an arc point = calculatePoint(angle + segment_angle, outer_radius) path['d'] += self.parsePathData('A', [outer_radius, outer_radius]) + \ '0 0 1' + self.parsePathData(' ', point) # Go to the fourth point in the segment point = calculatePoint(angle + segment_angle, outer_radius - width) path['d'] += self.parsePathData('L', point) # Go to the beginning in the segment, draw an arc point = calculatePoint(angle, outer_radius - width) # 'Z' closes the path path['d'] += (self.parsePathData( 'A', [outer_radius - width, outer_radius - width]) + '0 0 0' + self.parsePathData(' ', point) + ' Z') # Return the path return path
def joinFillsWithNode ( self, node, stroke_width, path ): ''' Generate a SVG <path> element containing the path data "path". Then put this new <path> element into a <group> with the supplied node. This means making a new <group> element and moving node under it with the new <path> as a sibling element. ''' if ( not path ) or ( len( path ) == 0 ): return # Make a new SVG <group> element whose parent is the parent of node parent = node.getparent() #was: if not parent: if parent is None: parent = self.document.getroot() g = inkex.etree.SubElement( parent, inkex.addNS( 'g', 'svg' ) ) # Move node to be a child of this new <g> element g.append( node ) # Now make a <path> element which contains the hatches & is a child # of the new <g> element style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': '%f' % stroke_width} line_attribs = { 'style':simplestyle.formatStyle( style ), 'd': path } tran = node.get( 'transform' ) if ( tran != None ) and ( tran != '' ): line_attribs['transform'] = tran inkex.etree.SubElement( g, inkex.addNS( 'path', 'svg' ), line_attribs )
def draw_SVG_circle(parent, r, cx, cy, name, style): " add an SVG circle entity to parent " circ_attribs = {'style': simplestyle.formatStyle(style), 'cx': str(cx), 'cy': str(cy), 'r': str(r), inkex.addNS('label','inkscape'):name} circle = inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs )
def draw_SVG_circle(r, cx, cy, width, fill, name, parent): style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': fill } circ_attribs = {'style':simplestyle.formatStyle(style), 'cx':str(cx), 'cy':str(cy), 'r':str(r), inkex.addNS('label','inkscape'):name} circle = inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs )
def change_attribute(self, node, attribute): for key, value in attribute.items(): if key == 'preserveAspectRatio': # set presentation attribute if value != "unset": node.set(key, str(value)) else: if node.get(key): del node.attrib[key] elif key == 'image-rendering': node_style = simplestyle.parseStyle(node.get('style')) if key not in node_style: # set presentation attribute if value != "unset": node.set(key, str(value)) else: if node.get(key): del node.attrib[key] else: # set style property if value != "unset": node_style[key] = str(value) else: del node_style[key] node.set('style', simplestyle.formatStyle(node_style)) else: pass
def line(self,points): """ Draw a line from point at (x1, y1) to point at (x2, y2). Style of line is hard coded and specified by 's'. """ # define the motions path = ('M%.4f,%.4fL' % tuple(points[0][:2])) + 'L'.join([('%f,%f' % tuple(a[:2])) for a in points[1:]]) # define the stroke style s = {'stroke-linejoin': 'miter', 'stroke-width': self.options.linewidth, 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': self.options.linecolor, 'stroke-linecap': 'round', 'fill': 'none' } ## Attributes for new element attribs = {'style' : simplestyle.formatStyle(s), 'd' : path} ## Add new element inkex.etree.SubElement(self.current_layer, inkex.addNS('path', 'svg'), attribs)
def effect(self): for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg')) new = inkex.etree.SubElement(self.group,inkex.addNS('path','svg')) try: t = node.get('transform') self.group.set('transform', t) except: pass s = simplestyle.parseStyle(node.get('style')) s['stroke-linecap']='round' s['stroke-width']=self.options.dotsize new.set('style', simplestyle.formatStyle(s)) a =[] p = simplepath.parsePath(node.get('d')) num = 1 for cmd,params in p: if cmd != 'Z': a.append(['M',params[-2:]]) a.append(['L',params[-2:]]) self.addText(self.group,params[-2],params[-1],num) num += 1 new.set('d', simplepath.formatPath(a)) node.clear()
def effect(self): for id, node in self.selected.iteritems(): if node.tagName == 'path': p = simplepath.parsePath(node.attributes.getNamedItem('d').value) a =[] pen = None subPathStart = None for cmd,params in p: if cmd == 'C': a.extend([['M', params[:2]], ['L', pen], ['M', params[2:4]], ['L', params[-2:]]]) if cmd == 'Q': a.extend([['M', params[:2]], ['L', pen], ['M', params[:2]], ['L', params[-2:]]]) if cmd == 'M': subPathStart = params if cmd == 'Z': pen = subPathStart else: pen = params[-2:] if len(a) > 0: new = self.document.createElement('svg:path') s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#000000', 'stroke-linecap': 'butt', 'fill': 'none'} new.setAttribute('style', simplestyle.formatStyle(s)) new.setAttribute('d', simplepath.formatPath(a)) node.parentNode.appendChild(new)
def effect(self): s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px', 'stroke-opacity': '1.0', 'fill-opacity': '1.0', 'stroke': '#000000', 'stroke-linecap': 'butt', 'fill': 'none'} attribs = {'style':simplestyle.formatStyle(s),'d':self.iterate()} inkex.etree.SubElement(self.current_layer,inkex.addNS('path','svg'),attribs)
def draw_crop_line(self, x1, y1, x2, y2, name, parent): style = { 'stroke': '#000000', 'stroke-width': str(self.stroke_width), 'fill': 'none'} line_attribs = {'style': simplestyle.formatStyle(style), 'id': name, 'd': 'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)} inkex.etree.SubElement(parent, 'path', line_attribs)
def drawCircles(self, circles, trans_point = (0.0, 0.0)): parent = self.current_layer i = 0 for layer in circles: for c in layer: x = trans_point[0] + c.x y = trans_point[1] + c.y if not self.options.tinned: material = 'CU' color = '#aa4400' else: material = 'CU-T' color = '#808080' style = {'stroke': 'none', 'fill': color} attribs = {'cx': str(x), 'cy': str(y), 'r': str(c.r), inkex.addNS('label', 'inkscape'):"is%d" %i, 'material':material, 'style': simplestyle.formatStyle(style)} inkex.etree.SubElement(parent, inkex.addNS('circle', 'svg'), attribs) i += 1
def effect(self): """ Calculate Gear factors from inputs. - Make list of radii, angles, and centers for each tooth and iterate through them - Turn on other visual features e.g. cross, rack, annotations, etc """ path_stroke = '#000000' # might expose one day path_fill = 'none' # no fill - just a line path_stroke_width = 0.6 # might expose one day path_stroke_light = path_stroke_width * 0.25 # guides are thinner # warnings = [] # list of extra messages to be shown in annotations # calculate unit factor for units defined in dialog. unit_factor = self.calc_unit_factor() # User defined options teeth = self.options.teeth # Angle of tangent to tooth at circular pitch wrt radial line. angle = self.options.angle # Clearance: Radial distance between top of tooth on one gear to # bottom of gap on another. clearance = self.options.clearance * unit_factor mount_hole = self.options.mount_hole * unit_factor # for spokes mount_radius = self.options.mount_diameter * 0.5 * unit_factor spoke_count = self.options.spoke_count spoke_width = self.options.spoke_width * unit_factor holes_rounding = self.options.holes_rounding * unit_factor # unused # visible guide lines centercross = self.options.centercross # draw center or not (boolean) pitchcircle = self.options.pitchcircle # draw pitch circle or not (boolean) # Accuracy of teeth curves accuracy_involute = 20 # Number of points of the involute curve accuracy_circular = 9 # Number of points on circular parts if self.options.accuracy is not None: if self.options.accuracy == 0: # automatic if teeth < 10: accuracy_involute = 20 elif teeth < 30: accuracy_involute = 12 else: accuracy_involute = 6 else: accuracy_involute = self.options.accuracy accuracy_circular = max(3, int(accuracy_involute / 2) - 1) # never less than three # print >>self.tty, "accuracy_circular=%s accuracy_involute=%s" % (accuracy_circular, accuracy_involute) # Pitch (circular pitch): Length of the arc from one tooth to the next) # Pitch diameter: Diameter of pitch circle. pitch = self.calc_circular_pitch(unit_factor) # Replace section below with this call to get the combined gear_calculations() above (pitch_radius, base_radius, addendum, dedendum, outer_radius, root_radius, tooth) = gear_calculations(teeth, pitch, angle, clearance, self.options.internal_ring, self.options.profile_shift * 0.01) # Detect Undercut of teeth ## undercut = int(ceil(undercut_min_teeth( angle ))) ## needs_undercut = teeth < undercut #? no longer needed ? if have_undercut(teeth, angle, 1.0): min_teeth = int(ceil(undercut_min_teeth(angle, 1.0))) min_angle = undercut_min_angle(teeth, 1.0) + .1 max_k = undercut_max_k(teeth, angle) msg = "Undercut Warning: This gear (%d teeth) will not work well.\nTry tooth count of %d or more,\nor a pressure angle of %.1f [deg] or more,\nor try a profile shift of %d %%.\nOr other decent combinations." % ( teeth, min_teeth, min_angle, int(100. * max_k) - 100.) # alas annotation cannot handle the degree symbol. Also it ignore newlines. # so split and make a list warnings.extend(msg.split("\n")) if self.options.undercut_alert: inkex.debug(msg) else: print >> self.tty, msg # All base calcs done. Start building gear points = generate_spur_points(teeth, base_radius, pitch_radius, outer_radius, root_radius, accuracy_involute, accuracy_circular) ## half_thick_angle = two_pi / (4.0 * teeth ) #?? = pi / (2.0 * teeth) ## pitch_to_base_angle = involute_intersect_angle( base_radius, pitch_radius ) ## pitch_to_outer_angle = involute_intersect_angle( base_radius, outer_radius ) - pitch_to_base_angle ## ## start_involute_radius = max(base_radius, root_radius) ## radii = linspace(start_involute_radius, outer_radius, accuracy_involute) ## angles = [involute_intersect_angle(base_radius, r) for r in radii] ## ## centers = [(x * two_pi / float( teeth) ) for x in range( teeth ) ] ## points = [] ## ## for c in centers: ## # Angles ## pitch1 = c - half_thick_angle ## base1 = pitch1 - pitch_to_base_angle ## offsetangles1 = [ base1 + x for x in angles] ## points1 = [ point_on_circle( radii[i], offsetangles1[i]) for i in range(0,len(radii)) ] ## ## pitch2 = c + half_thick_angle ## base2 = pitch2 + pitch_to_base_angle ## offsetangles2 = [ base2 - x for x in angles] ## points2 = [ point_on_circle( radii[i], offsetangles2[i]) for i in range(0,len(radii)) ] ## ## points_on_outer_radius = [ point_on_circle(outer_radius, x) for x in linspace(offsetangles1[-1], offsetangles2[-1], accuracy_circular) ] ## ## if root_radius > base_radius: ## pitch_to_root_angle = pitch_to_base_angle - involute_intersect_angle(base_radius, root_radius ) ## root1 = pitch1 - pitch_to_root_angle ## root2 = pitch2 + pitch_to_root_angle ## points_on_root = [point_on_circle (root_radius, x) for x in linspace(root2, root1+(two_pi/float(teeth)), accuracy_circular) ] ## p_tmp = points1 + points_on_outer_radius[1:-1] + points2[::-1] + points_on_root[1:-1] # [::-1] reverses list; [1:-1] removes first and last element ## else: ## points_on_root = [point_on_circle (root_radius, x) for x in linspace(base2, base1+(two_pi/float(teeth)), accuracy_circular) ] ## p_tmp = points1 + points_on_outer_radius[1:-1] + points2[::-1] + points_on_root # [::-1] reverses list ## ## points.extend( p_tmp ) path = points_to_svgd(points) bbox_center = points_to_bbox_center(points) # Spokes (add to current path) if not self.options.internal_ring: # only draw internals if spur gear spokes_path, msg = generate_spokes_path(root_radius, spoke_width, spoke_count, mount_radius, mount_hole, unit_factor, self.options.units) warnings.extend(msg) path += spokes_path # Draw mount hole # A : rx,ry x-axis-rotation, large-arch-flag, sweepflag x,y r = mount_hole / 2 path += ("M %f,%f" % (0, r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, -r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, r)) else: # its a ring gear # which only has an outer ring where width = spoke width r = outer_radius + spoke_width path += ("M %f,%f" % (0, r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, -r) + "A %f,%f %s %s %s %f,%f" % (r, r, 0, 0, 0, 0, r)) # Embed gear in group to make animation easier: # Translate group, Rotate path. t = 'translate(' + str(self.view_center[0]) + ',' + str( self.view_center[1]) + ')' g_attribs = { inkex.addNS('label', 'inkscape'): 'Gear' + str(teeth), inkex.addNS('transform-center-x', 'inkscape'): str(-bbox_center[0]), inkex.addNS('transform-center-y', 'inkscape'): str(-bbox_center[1]), 'transform': t, 'info': 'N:' + str(teeth) + '; Pitch:' + str(pitch) + '; Pressure Angle: ' + str(angle) } # add the group to the current layer g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) # Create gear path under top level group style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_width } gear_attribs = {'style': simplestyle.formatStyle(style), 'd': path} gear = inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), gear_attribs) # Add center if centercross: style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_light } cs = str(pitch / 3) # centercross length d = 'M-' + cs + ',0L' + cs + ',0M0,-' + cs + 'L0,' + cs # 'M-10,0L10,0M0,-10L0,10' center_attribs = { inkex.addNS('label', 'inkscape'): 'Center cross', 'style': simplestyle.formatStyle(style), 'd': d } center = inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), center_attribs) # Add pitch circle (for mating) if pitchcircle: style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_light } draw_SVG_circle(g, pitch_radius, 0, 0, 'Pitch circle', style) # Add Rack (below) if self.options.drawrack: base_height = self.options.base_height * unit_factor tab_width = self.options.base_tab * unit_factor tooth_count = self.options.teeth_length (points, guide_path) = generate_rack_points(tooth_count, pitch, addendum, angle, base_height, tab_width, clearance, pitchcircle) path = points_to_svgd(points) # position below Gear, so that it meshes nicely # xoff = 0 ## if teeth % 4 == 2. # xoff = -0.5*pitch ## if teeth % 4 == 0. # xoff = -0.75*pitch ## if teeth % 4 == 3. # xoff = -0.25*pitch ## if teeth % 4 == 1. xoff = (-0.5, -0.25, 0, -0.75)[teeth % 4] * pitch t = 'translate(' + str(xoff) + ',' + str(pitch_radius) + ')' g_attribs = { inkex.addNS('label', 'inkscape'): 'RackGear' + str(tooth_count), 'transform': t } rack = inkex.etree.SubElement(g, 'g', g_attribs) # Create SVG Path for gear style = { 'stroke': path_stroke, 'fill': 'none', 'stroke-width': path_stroke_width } gear_attribs = {'style': simplestyle.formatStyle(style), 'd': path} gear = inkex.etree.SubElement(rack, inkex.addNS('path', 'svg'), gear_attribs) if guide_path is not None: style2 = { 'stroke': path_stroke, 'fill': 'none', 'stroke-width': path_stroke_light } gear_attribs2 = { 'style': simplestyle.formatStyle(style2), 'd': guide_path } gear = inkex.etree.SubElement(rack, inkex.addNS('path', 'svg'), gear_attribs2) # Add Annotations (above) if self.options.annotation: outer_dia = outer_radius * 2 if self.options.internal_ring: outer_dia += 2 * spoke_width notes = [] notes.extend(warnings) #notes.append('Document (%s) scale conversion = %2.4f' % (self.document.getroot().find(inkex.addNS('namedview', 'sodipodi')).get(inkex.addNS('document-units', 'inkscape')), unit_factor)) notes.extend([ 'Teeth: %d CP: %2.4f(%s) ' % (teeth, pitch / unit_factor, self.options.units), 'DP: %2.3f Module: %2.4f' % (pi / pitch * unit_factor, pitch / pi * 25.4), 'Pressure Angle: %2.2f degrees' % (angle), 'Pitch diameter: %2.3f %s' % (pitch_radius * 2 / unit_factor, self.options.units), 'Outer diameter: %2.3f %s' % (outer_dia / unit_factor, self.options.units), 'Root diameter: %2.3f %s' % (root_radius * 2 / unit_factor, self.options.units), 'Base diameter: %2.3f %s' % (base_radius * 2 / unit_factor, self.options.units) #, #'Addendum: %2.4f %s' % (addendum / unit_factor, self.options.units), #'Dedendum: %2.4f %s' % (dedendum / unit_factor, self.options.units) ]) # text height relative to gear size. # ranges from 10 to 22 over outer radius size 60 to 360 text_height = max(10, min(10 + (outer_dia - 60) / 24, 22)) # position above y = -outer_radius - (len(notes) + 1) * text_height * 1.2 for note in notes: self.add_text(g, note, [0, y], text_height) y += text_height * 1.2
#!/usr/bin/env python # We will use the inkex module with the predefined Effect base class. import inkex # The simplestyle module provides functions for style parsing. import simplestyle from math import * from collections import namedtuple #Note: keep in mind that SVG coordinates start in the top-left corner i.e. with an inverted y-axis # first define some SVG primitives (we do not use them all so a cleanup may be in order) objStyle = simplestyle.formatStyle( {'stroke': '#000000', 'stroke-width': 0.28, 'fill': 'none' }) greenStyle = simplestyle.formatStyle( {'stroke': '#00ff00', 'stroke-width': 0.28, 'fill': 'none' }) def draw_SVG_square((w,h), (x,y), parent): attribs = { 'style': objStyle, 'height': str(h), 'width': str(w), 'x': str(x), 'y': str(y)
def export_HATCH(): # mandatory group codes : (10, 20, 70, 72, 92, 93) (x, y, fill, Edge Type, Path Type, Number of edges) if vals[groups['10']] and vals[groups['20']] and vals[ groups['70']] and vals[groups['72']] and vals[ groups['92']] and vals[groups['93']]: if len(vals[groups['10']]) > 1 and len(vals[groups['20']]) == len( vals[groups['10']]): # optional group codes : (11, 21, 40, 50, 51, 73) (x, y, r, angle1, angle2, CCW) i10 = 1 # count start points i11 = 0 # count line end points i40 = 0 # count circles i72 = 0 # count edge type flags path = '' for i in range(0, len(vals[groups['93']])): xc = vals[groups['10']][i10] yc = vals[groups['20']][i10] if vals[groups['72']][i72] == 2: # arc rm = scale * vals[groups['40']][i40] a1 = vals[groups['50']][i40] path += 'M %f,%f ' % ( xc + rm * math.cos(a1 * math.pi / 180.0), yc + rm * math.sin(a1 * math.pi / 180.0)) else: a1 = 0 path += 'M %f,%f ' % (xc, yc) for j in range(0, vals[groups['93']][i]): if vals[groups['92']][i] & 2: # polyline if j > 0: path += 'L %f,%f ' % (vals[groups['10']][i10], vals[groups['20']][i10]) if j == vals[groups['93']][i] - 1: i72 += 1 elif vals[groups['72']][i72] == 2: # arc xc = vals[groups['10']][i10] yc = vals[groups['20']][i10] rm = scale * vals[groups['40']][i40] a2 = vals[groups['51']][i40] diff = (a2 - a1 + 360) % (360) sweep = 1 - vals[groups['73']][i40] # sweep CCW large = 0 # large-arc-flag if diff: path += 'A %f,%f 0.0 %d %d %f,%f ' % ( rm, rm, large, sweep, xc + rm * math.cos(a2 * math.pi / 180.0), yc + rm * math.sin(a2 * math.pi / 180.0)) else: path += 'A %f,%f 0.0 %d %d %f,%f ' % ( rm, rm, large, sweep, xc + rm * math.cos( (a1 + 180.0) * math.pi / 180.0), yc + rm * math.sin( (a1 + 180.0) * math.pi / 180.0)) path += 'A %f,%f 0.0 %d %d %f,%f ' % ( rm, rm, large, sweep, xc + rm * math.cos(a1 * math.pi / 180.0), yc + rm * math.sin(a1 * math.pi / 180.0)) i40 += 1 i72 += 1 elif vals[groups['72']][i72] == 1: # line path += 'L %f,%f ' % (scale * (vals[groups['11']][i11] - xmin), height - scale * (vals[groups['21']][i11] - ymin)) i11 += 1 i72 += 1 i10 += 1 path += "z " if vals[groups['70']][0]: style = simplestyle.formatStyle({'fill': '%s' % color}) else: style = simplestyle.formatStyle({ 'fill': 'url(#Hatch)', 'fill-opacity': '1.0' }) attribs = {'d': path, 'style': style} inkex.etree.SubElement(layer, 'path', attribs)
if id_ is not None: attribs.update({'id': id_}) obj = inkex.etree.SubElement(parent, inkex.addNS('rect', 'svg'), attribs) return obj def draw_circle(self, (x, y), r, color, parent, id_): style = { 'stroke': 'none', 'stroke-width': '1', 'fill': color, "mix-blend-mode": "multiply" } attribs = { 'style': simplestyle.formatStyle(style), 'cx': str(x), 'cy': str(y), 'r': str(r) } if id_ is not None: attribs.update({'id': id_}) obj = inkex.etree.SubElement(parent, inkex.addNS('circle', 'svg'), attribs) return obj def draw_ellipse(self, (x, y), (r1, r2), color, parent, id_, transform): style = { 'stroke': 'none', 'stroke-width': '1',
class raster_to_svg_ordered_dithering(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) self.OptionParser.add_option( "-t", "--width", action="store", type="int", dest="width", default=200, help= "this variable will be used to resize the original selected image to a width of whatever \ you enter and height proportional to the new width, thus maintaining the aspect ratio" ) def getImagePath(self, node, xlink): absref = node.get(inkex.addNS('absref', 'sodipodi')) url = urlparse(xlink) href = url2pathname(url.path) path = '' if href is not None: path = os.path.realpath(href) if (not os.path.isfile(path)): if absref is not None: path = absref try: path = unicode(path, "utf-8") except TypeError: path = path if (not os.path.isfile(path)): inkex.errormsg( _("No xlink:href or sodipodi:absref attributes found, " + "or they do not point to an existing file! Unable to find image file." )) if path: inkex.errormsg(_("Sorry we could not locate %s") % str(path)) return False if (os.path.isfile(path)): return path def getImageData(self, xlink): """ Read, decode and return data of embedded image """ comma = xlink.find(',') data = '' if comma > 0: data = base64.decodestring(xlink[comma:]) else: inkex.errormsg(_("Failed to read embedded image data.")) return data def getImage(self, node): """ Parse link attribute of node and retrieve image data """ xlink = node.get(inkex.addNS('href', 'xlink')) image = '' if xlink is None or xlink[:5] != 'data:': # linked bitmap image path = self.getImagePath(node, xlink) if path: image = Image.open(path) elif xlink[:4] == 'data': # embedded bitmap image data = self.getImageData(xlink) if data: image = Image.open(StringIO.StringIO(data)) else: # unsupported type of link detected inkex.errormsg(_("Unsupported type of 'xlink:href'")) return image def draw_rectangle(self, (x, y), (l, b), color, parent, id_): style = { 'stroke': 'none', 'stroke-width': '1', 'fill': color, "mix-blend-mode": "multiply" } attribs = { 'style': simplestyle.formatStyle(style), 'x': str(x), 'y': str(y), 'width': str(l), 'height': str(b) } if id_ is not None: attribs.update({'id': id_}) obj = inkex.etree.SubElement(parent, inkex.addNS('rect', 'svg'), attribs) return obj
def effect(self): global debug if self.options.version: print __version__ sys.exit(0) if self.options.invert is not None: self.invert_image = self.options.invert if self.options.remove is not None: self.replace_image = self.options.remove if self.options.megapixels is not None: self.megapixel_limit = self.options.megapixels if self.options.candidates is not None: self.candidates = self.options.candidates if self.options.despecle is not None: self.filter_median = self.options.despecle if self.options.equal_light is not None: self.filter_equal_light = self.options.equal_light if self.options.debug is not None: debug = self.options.debug self.calc_unit_factor() if not len(self.selected.items()): inkex.errormsg(_("Please select an image.")) return for id, node in self.selected.iteritems(): if debug: print >> self.tty, "id=" + str(id), "tag=" + str(node.tag) if node.tag != inkex.addNS('image', 'svg'): inkex.errormsg( _("Object " + id + " is not an image. seen:" + str(node.tag) + " expected:" + inkex.addNS('image', 'svg') + "\n Try - Object->Ungroup")) return # handle two cases. Embedded and linked images # <image .. xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAT8AA ..." preserveAspectRatio="none" height="432" width="425" transform="matrix(1,0,-0.52013328,0.85408511,0,0)"/> # <image .. xlink:href="file:///home/jw/schaf.png" href = str(node.get(inkex.addNS('href', 'xlink'))) # ###################### # # dump the entire svg to file, so that we can examine what an image is. # f=open(self.dumpname, 'w') # f.write(href) # f.close() # if debug: print >>self.tty, "Dump written to "+self.dumpname # # ###################### if href[:7] == 'file://': filename = href[7:] if debug: print >> self.tty, "linked image: =" + filename elif href[0] == '/' or href[0] == '.': filename = href if debug: print >> self.tty, "linked image path: =" + filename elif href[:11] == 'data:image/': l = href[11:].index(';') type = href[11:11 + l] # 'png' 'jpeg' if debug: print >> self.tty, "embedded image: " + href[:11 + l] img = base64.decodestring(href[11 + l + 8:]) f = tempfile.NamedTemporaryFile(mode="wb", suffix="." + type, delete=False) f.write(img) filename = f.name f.close() else: inkex.errormsg( _("Neither file:// nor data:image/png; prefix. Cannot parse PNG image href " + href)) sys.exit(1) if debug: print >> self.tty, "filename=" + filename # path_svg, stroke_width, im_size = self.svg_centerline_trace( filename) xml = inkex.etree.fromstring(path_svg) try: path_d = xml.find('path').attrib['d'] except: inkex.errormsg( _("Couldn't trace the path. Please make sure that the checkbox for tracing bright lines is set correctly and that your drawing has enough contrast." )) sys.exit(1) # images can also just have a transform attribute, and no x or y, # could be replaced by a (slower) call to command line, or by computeBBox from simpletransform x_off = float(node.get('x', 0)) y_off = float(node.get('y', 0)) sx = float(node.get('width')) / im_size[0] sy = float(node.get('height')) / im_size[1] if debug: print >> self.tty, "im_width ", node.get('width'), "sx=", sx if debug: print >> self.tty, "im_height ", node.get('height'), "sy=", sy if debug: print >> self.tty, "im_x ", x_off if debug: print >> self.tty, "im_y ", y_off if debug: print >> self.tty, "pixel_size= ", im_size ## map the coordinates of the returned pixel path to the coordinates of the original SVG image. matrix = "translate(%g,%g) scale(%g,%g)" % (x_off, y_off, sx, sy) # if href[:5] == 'data:': os.unlink( filename ) ## it was a temporary file (representing an embedded image). # # Create SVG Path style = { 'stroke': '#000000', 'fill': 'none', 'stroke-linecap': 'round', 'stroke-width': stroke_width } if self.invert_image: style['stroke'] = '#777777' path_attr = { 'style': simplestyle.formatStyle(style), 'd': path_d, 'transform': matrix } ## insert the new path object inkex.etree.SubElement(self.current_layer, inkex.addNS('path', 'svg'), path_attr) ## delete the old image object if self.replace_image: node.getparent().remove(node)
import simplestyle,inkex def draw_SVG_square((w,h), (x,y), parent,fill= '#FF0000'): style = { 'stroke' : 'none', 'stroke-width' : '0.5', 'fill' : fill } attribs = { 'style' : simplestyle.formatStyle(style), 'height' : str(h), 'width' : str(w), 'x' : str(x), 'y' : str(y) } circ = inkex.etree.SubElement(parent, inkex.addNS('rect','svg'), attribs ) def draw_SVG_path(d, parent,fill= '#FF0000',strokeWidth="0.5"): style = { 'stroke' : '#000000', 'stroke-width' : strokeWidth, 'fill' : fill } attribs = { 'style' : simplestyle.formatStyle(style), 'd' : str(d) } circ = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), attribs ) def draw_SVG_line( (x1, y1), (x2, y2), style, name, parent): line_style = { 'stroke': style.l_col, 'stroke-width':str(style.l_th), 'fill': style.l_fill
def effect(self): poly = self.options.poly size = self.options.size eC = polyhedronData[poly]['edgeCoordinates'] iEI = polyhedronData[poly]['insideEdgeIndices'] oEI = polyhedronData[poly]['outsideEdgeIndices'] oED = polyhedronData[poly]['outsideEdgeDegrees'] sidelen = sqrt((eC[oEI[0][0]-1][0] - eC[oEI[0][1]-1][0])**2 + \ (eC[oEI[0][0]-1][1] - eC[oEI[0][1]-1][1])**2) scale = size / sidelen # Translate group, Rotate path. t = 'translate(' + str(self.view_center[0]) + ',' + str( self.view_center[1]) + ')' g_attribs = { inkex.addNS('label', 'inkscape'): 'Polygon ' + str(poly), 'transform': t } g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) gsub_attribs = { inkex.addNS('label', 'inkscape'): 'Polygon ' + str(poly) + 'border' } gsub = inkex.etree.SubElement(g, 'g', gsub_attribs) # Create SVG Path for gear cutStyle = {'stroke': '#0000FF', 'fill': 'none'} perfStyle = {'stroke': '#FF0000', 'fill': 'none'} textStyle = { 'font-size': str(size / 4), 'font-family': 'arial', 'text-anchor': 'middle', 'text-align': 'center', 'fill': '#222' } numOEI = len(oEI) for edgeIndex in range(numOEI): eX1 = eC[oEI[edgeIndex][0] - 1][0] eY1 = eC[oEI[edgeIndex][0] - 1][1] eX2 = eC[oEI[edgeIndex][1] - 1][0] eY2 = eC[oEI[edgeIndex][1] - 1][1] origin = (eX1 * scale, eY1 * scale) edgelen = sqrt((eX1 - eX2)**2 + (eY1 - eY2)**2) edgesize = size * (edgelen / sidelen) prevAngle = (oED[(edgeIndex - 1) % numOEI] + 180 - oED[edgeIndex]) % 360 nextAngle = (oED[edgeIndex] + 180 - oED[(edgeIndex + 1) % numOEI]) % 360 if angleOverride.has_key(poly): if angleOverride[poly].has_key('prev'): if angleOverride[poly]['prev'].has_key(edgeIndex): prevAngle = angleOverride[poly]['prev'][edgeIndex] if angleOverride[poly].has_key('next'): if angleOverride[poly]['next'].has_key(edgeIndex): nextAngle = angleOverride[poly]['next'][edgeIndex] trans = 'translate(' + str(origin[0]) + ',' + str( origin[1]) + ') rotate(' + str( oED[edgeIndex]) + ') scale(' + str(edgesize / 100.0) + ')' limitAngle = min(prevAngle, nextAngle) tab = self.get_tab(limitAngle) slot = self.get_slot(limitAngle) # the "special" tabs are all skewed one way or the other, to # make room for tight turns. This determines if it is the previous # or next angle that is the tight one, and flips the tab or slot if # needed. if (nextAngle == limitAngle): trans += ' translate(100.0, 0) scale(-1,1)' tab_group_attribs = { inkex.addNS('label', 'inkscape'): 'tab', 'transform': trans } tab_group = inkex.etree.SubElement(gsub, 'g', tab_group_attribs) midX = (eX2 - eX1) / 2 + eX1 midY = (eY2 - eY1) / 2 + eY1 text_attrib = { 'style': simplestyle.formatStyle(textStyle), 'x': str(midX * scale), 'y': str(midY * scale) } # inkex.etree.SubElement(gsub, 'text', text_attrib).text = str(edgeIndex) if ((edgeIndex % 2) == 0): edgetype = tab else: edgetype = slot for path in edgetype['cut']: gear_attribs = { 'style': simplestyle.formatStyle(cutStyle), 'd': path } gear = inkex.etree.SubElement(tab_group, inkex.addNS('path', 'svg'), gear_attribs) for path in edgetype['perf']: gear_attribs = { 'style': simplestyle.formatStyle(perfStyle), 'd': path } gear = inkex.etree.SubElement(tab_group, inkex.addNS('path', 'svg'), gear_attribs) gsub_attribs = { inkex.addNS('label', 'inkscape'): 'Polygon ' + str(poly) + 'inside' } gsub = inkex.etree.SubElement(g, 'g', gsub_attribs) for edge in iEI: points = [(eC[edge[0] - 1][0] * scale, eC[edge[0] - 1][1] * scale), (eC[edge[1] - 1][0] * scale, eC[edge[1] - 1][1] * scale)] path = points_to_svgd(points) perf_attribs = { 'style': simplestyle.formatStyle(perfStyle), 'd': path } gear = inkex.etree.SubElement(gsub, inkex.addNS('path', 'svg'), perf_attribs)
def set_prop(node, prop, val): """Set style property on node.""" sdict = simplestyle.parseStyle(node.get('style')) sdict[prop] = val node.set('style', simplestyle.formatStyle(sdict))
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ''' import inkex import simplestyle, sys from simpletransform import computePointInNode from math import * def draw_SVG_tri((x1, y1), (x2, y2), (x3, y3), (ox, oy), width, name, parent): style = {'stroke': '#000000', 'stroke-width': str(width), 'fill': 'none'} tri_attribs = { 'style': simplestyle.formatStyle(style), inkex.addNS('label', 'inkscape'): name, 'd': 'M ' + str(x1 + ox) + ',' + str(y1 + oy) + ' L ' + str(x2 + ox) + ',' + str(y2 + oy) + ' L ' + str(x3 + ox) + ',' + str(y3 + oy) + ' L ' + str(x1 + ox) + ',' + str(y1 + oy) + ' z' } inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), tri_attribs) def angle_from_3_sides(a, b, c): #return the angle opposite side c cosx = (a * a + b * b - c * c) / (2 * a * b) #use the cosine rule return acos(cosx)
def effect(self): root = self.document.getroot() count = 0 for path in self.document.xpath('//svg:path', namespaces=inkex.NSS): # Default settings for now stroke, fill, color = ('none', 'none', 'unknown') # Get the paths style attribute style = simplestyle.parseStyle(path.get('style', '')) # Obtain the fill color from the path's style attribute if 'fill' in style: color = style['fill'] if self.options.fillRegions: fill = color if self.options.outlineRegions: stroke = color # Now add or change the fill color in the path's style style['fill'] = fill # Add or change the stroke behavior in the path's style style['stroke'] = stroke # And change the style attribute for the path path.set('style', simplestyle.formatStyle(style)) # Create a group <g> element under the document root layer = inkex.etree.SubElement(root, inkex.addNS('g', 'svg')) # Add Inkscape layer attributes to this new group count += 1 layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') layer.set(inkex.addNS('label', 'inkscape'), '{0:d} - {1}'.format(count, color)) # Now move this path from where it was to being a child # of this new group/layer we just made layer.append(path) # Remove any image # For color scans, Trace Bitmap seems to put the # image in the same layer & group as the traced regions. # BUT, for gray scans, it seems to leave the image by # itself as a child of the root document if self.options.removeImage: for node in self.document.xpath('//svg:image', namespaces=inkex.NSS): parent = node.getparent() if (parent.tag == 'svg') or (parent.tag == inkex.addNS( 'svg', 'svg')): parent.remove(node) else: gparent = parent.getparent() try: gparent.remove(parent) except: parent.remove(node) inkex.errormsg(gettext.gettext('Finished. Created %d layers') % count)
def effect(self): """ Fonction principale Surchage la fonction de la classe de base Dessine quelques elements sur le docuement SVG """ # Recupere le document SVG principal svg = self.document.getroot() layer = self.current_layer # Recuperation de la hauteur et de la largeur de la feuille width = inkex.unittouu(svg.get('width')) height = inkex.unittouu(svg.attrib['height']) """ §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ LA RÈGLE §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ """ x_org = 10 #width / 20 x_pas = width / 21 y_org = 10 #height / 10 y_pas = 20 nLargeurTrait = 1 # Center text horizontally with CSS style. textstyle = {'text-align' : 'left', \ 'text-anchor': 'top', \ 'font-size': '12pt', \ 'fill':'rgb(0, 0, 0)'} ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) ligne.set('x1', str(x_org)) ligne.set('y1', str(y_org)) ligne.set('x2', str(x_org + 20 * x_pas)) ligne.set('y2', str(y_org)) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne) for n in range(21): x_pos = x_org + n * x_pas ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) ligne.set('x1', str(x_pos)) ligne.set('y1', str(y_org)) ligne.set('x2', str(x_pos)) ligne.set('y2', str(y_org + y_pas)) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne) # Creation d'un element texte texte = inkex.etree.Element(inkex.addNS('text', 'svg')) texte.text = str(n) # Set text position to center of document. textDecal = 4 if n > 9: textDecal = 2 * textDecal texte.set('x', str(x_pos - textDecal)) texte.set('y', str(y_org + 2 * y_pas)) texte.set('style', simplestyle.formatStyle(textstyle)) # Ajoute le texte au calque layer.append(texte) y_pas = 15 for n in range(20): x_pos = x_org + x_pas / 2 + n * x_pas ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) ligne.set('x1', str(x_pos)) ligne.set('y1', str(y_org)) ligne.set('x2', str(x_pos)) ligne.set('y2', str(y_org + y_pas)) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne) x_pas = width / 210 y_pas = 10 for n in range(200): x_pos = x_org + n * x_pas ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) ligne.set('x1', str(x_pos)) ligne.set('y1', str(y_org)) ligne.set('x2', str(x_pos)) ligne.set('y2', str(y_org + y_pas)) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne) """ §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ LE RAPPORTEUR §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ """ # Creation du demi-cercle x_org = width / 2 x_pas = width / 21 y_org = height / 2 y_pas = 20 nLargeurTrait = 1 radius = x_org demicercle = inkex.etree.Element(inkex.addNS('path', 'svg')) f = (0.0, y_org) svgd = 'M %.3f,%.3f ' % f a = (x_org, x_org) b = (width, y_org) svgd += 'A %.3f,%.3f 0 1 1 ' % a svgd += '%.3f,%.3f ' % b svgd += 'z' demicercle.set('d', svgd) demicercle.set('fill', 'none') demicercle.set('stroke', 'rgb(0, 0, 0)') demicercle.set('stroke-width', str(nLargeurTrait)) # Ajout du cercle sur le calque layer.append(demicercle) # graduations x_org = width / 2 x_pas = width / 21 y_org = height / 2 y_pas = 20 nLargeurTrait = 1 radius = x_org angle_pas = 10 coeff = 0.70 for n in range(19): ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) angle = radians(n * angle_pas) c = radius * cos(angle) s = radius * sin(angle) x1 = x_org + c y1 = y_org - s ligne.set('x1', str(x1)) ligne.set('y1', str(y1)) x2 = str(x_org + coeff * c) y2 = str(y_org - coeff * s) ligne.set('x2', x2) ligne.set('y2', y2) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne) # Creation d'un element texte texte = inkex.etree.Element(inkex.addNS('text', 'svg')) layer.append(texte) texte.text = str(10 * n) # + '°' texte.set('style', simplestyle.formatStyle(textstyle)) angle = radians(90 - n * angle_pas) f = (cos(angle), sin(angle), -sin(angle), cos(angle)) matrix = 'matrix(%s, %s, %s, %s,0,0)' % f texte.set('transform', matrix) #texte.set('x', x2) #texte.set('y', y2) texte.set('x', '634') texte.set('y', '-290') angle_pas = 10 coeff = 0.80 for n in range(18): ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) angle = radians(5 + n * angle_pas) c = radius * cos(angle) s = radius * sin(angle) x1 = x_org + c y1 = y_org - s ligne.set('x1', str(x1)) ligne.set('y1', str(y1)) x2 = x_org + coeff * c y2 = y_org - coeff * s ligne.set('x2', str(x2)) ligne.set('y2', str(y2)) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne) angle_pas = 1 coeff = 0.95 for n in range(180): ligne = inkex.etree.Element(inkex.addNS('line', 'svg')) angle = radians(n * angle_pas) c = radius * cos(angle) s = radius * sin(angle) x1 = x_org + c y1 = y_org - s ligne.set('x1', str(x1)) ligne.set('y1', str(y1)) x2 = x_org + coeff * c y2 = y_org - coeff * s ligne.set('x2', str(x2)) ligne.set('y2', str(y2)) ligne.set('stroke', 'rgb(0, 0, 0)') ligne.set('stroke-width', str(nLargeurTrait)) layer.append(ligne)
def recursiveFuseTransform(self, node, transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): transf = composeTransform(transf, parseTransform(node.get("transform", None))) if 'transform' in node.attrib: del node.attrib['transform'] if 'style' in node.attrib: style = node.attrib.get('style') style = simplestyle.parseStyle(style) update = False if 'stroke-width' in style: unit = self.getUnit(style.get('stroke-width').strip()) stroke_width = self.getVal(style.get('stroke-width').strip()) # pixelsnap ext assumes scaling is similar in x and y # and uses the x scale... # let's try to be a bit smarter stroke_width *= math.sqrt( (transf[0][0]**2 + transf[1][1]**2) / 2) style['stroke-width'] = self.valWithUnit(stroke_width, unit) update = True if update: style = simplestyle.formatStyle(style) node.attrib['style'] = style node = ApplyTransform.objectToPath(node) if 'd' in node.attrib: d = node.get('d') p = cubicsuperpath.parsePath(d) applyTransformToPath(transf, p) node.set('d', cubicsuperpath.formatPath(p)) elif node.tag == inkex.addNS('polygon', 'svg'): points = node.get('points') points = points.strip().split(' ') for k, p in enumerate(points): p = p.split(',') unit = self.getUnit(p[0]) p = [self.getVal(p[0]), self.getVal(p[1])] applyTransformToPoint(transf, p) p = [ self.valWithUnit(p[0], unit), self.valWithUnit(p[1], unit) ] p = ','.join(p) points[k] = p points = ' '.join(points) node.set('points', points) # if there is cx, there is also cy if 'cx' in node.attrib: cx = node.get('cx') cy = node.get('cy') unit = self.getUnit(cx) pt = [self.getVal(cx), self.getVal(cy)] applyTransformToPoint(transf, pt) node.set('cx', self.valWithUnit(pt[0], unit)) node.set('cy', self.valWithUnit(pt[1], unit)) if 'r' in node.attrib: unit = self.getUnit(node.get('r')) r = self.getVal(node.get('r')) # this is a circle: is the scale uniform? if transf[0][0] == transf[1][1]: r *= abs(transf[0][0]) node.set('r', self.valWithUnit(r, unit)) else: # transform is not uniform: go from circle to ellipse # NOTE!!! Inkscape currently applies this particular transform as soon as we touch the object. # therefore rx and ry are both assigned to r, otherwise the scaling is applied two times! # this is kind of a bug of the implementation rx = r #*abs(transf[0][0]) ry = r #*abs(transf[1][1]) node.set('rx', self.valWithUnit(rx, unit)) node.set('ry', self.valWithUnit(ry, unit)) del node.attrib['r'] node.tag = inkex.addNS('ellipse', 'svg') if 'rx' in node.attrib: unit = self.getUnit(node.get('rx')) rx = self.getVal(node.get('rx')) * abs(transf[0][0]) ry = self.getVal(node.get('ry')) * abs(transf[1][1]) node.set('rx', self.valWithUnit(rx, unit)) node.set('ry', self.valWithUnit(ry, unit)) if 'x' in node.attrib: unit = self.getUnit(node.get('x')) x = self.getVal(node.get('x')) * transf[0][0] y = self.getVal(node.get('y')) * transf[1][1] node.set('x', self.valWithUnit(x, unit)) node.set('y', self.valWithUnit(y, unit)) if 'width' in node.attrib: unit = self.getUnit(node.get('width')) w = self.getVal(node.get('width')) * transf[0][0] h = self.getVal(node.get('height')) * transf[1][1] if w < 0: xUnit = self.getUnit(node.get('x')) x = self.getVal(node.get('x')) x += w w = -w node.set('x', self.valWithUnit(x, xUnit)) if h < 0: yUnit = self.getUnit(node.get('y')) y = self.getVal(node.get('y')) y += h h = -h node.set('y', self.valWithUnit(y, yUnit)) node.set('width', self.valWithUnit(w, unit)) node.set('height', self.valWithUnit(h, unit)) for child in node.getchildren(): self.recursiveFuseTransform(child, transf)
def effect(self): global debug if self.options.version: print __version__ sys.exit(0) if self.options.invert is not None: self.invert_image = self.options.invert if self.options.remove is not None: self.replace_image = self.options.remove if self.options.megapixels is not None: self.megapixel_limit = self.options.megapixels if self.options.candidates is not None: self.candidates = self.options.candidates if self.options.despecle is not None: self.filter_median = self.options.despecle if self.options.equal_light is not None: self.filter_equal_light = self.options.equal_light if self.options.hairline is not None: self.hairline = self.options.hairline if self.options.hairline_width is not None: self.hairline_width = self.options.hairline_width # if self.options.debug is not None: debug = self.options.debug # self.options.debug = True self.calc_unit_factor() cliprect = None if self.options.cliprect: for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): print >>sys.stderr, "Error: id="+str(id)+" is a path.\nNeed a rectangle object for clipping." if node.tag == inkex.addNS('rect','svg'): if debug: print >>self.tty, "cliprect: id="+str(id), "node="+str(node.tag) cliprect = { 'x': float(node.get('x', 0)), 'y': float(node.get('y', 0)), 'w': float(node.get('width', 0)), 'h': float(node.get('height', 0)), 'node': node } if debug: print >>self.tty, "cliprect: id="+str(id), "cliprect="+str(cliprect) if not len(self.selected.items()): inkex.errormsg(_("Please select an image.")) return if cliprect is not None and len(self.selected.items()) < 2: inkex.errormsg(_("Please select an image. Only a cliprect was selected.")) return for id, node in self.selected.iteritems(): if debug: print >>self.tty, "id="+str(id), "tag="+str(node.tag) if self.options.cliprect and node.tag == inkex.addNS('rect','svg'): continue if node.tag != inkex.addNS('image','svg'): inkex.errormsg(_("Object "+id+" is NOT an image. seen:"+str(node.tag)+" expected:"+inkex.addNS('image','svg')+"\n Try - Object->Ungroup")) return # images can also just have a transform attribute, and no x or y, # FIXME: should find the image transformation! # could be replaced by a (slower) call to command line, or by computeBBox from simpletransform svg_x_off = float(node.get('x', 0)) svg_y_off = float(node.get('y', 0)) svg_img_w = float(node.get('width', 0.001)) svg_img_h = float(node.get('height', 0.001)) if cliprect is not None: # normalize cliprect into range 0..1 cliprect['x'] = cliprect['x'] - svg_x_off cliprect['y'] = cliprect['y'] - svg_y_off cliprect['x'] = cliprect['x'] / svg_img_w cliprect['y'] = cliprect['y'] / svg_img_h cliprect['w'] = cliprect['w'] / svg_img_w cliprect['h'] = cliprect['h'] / svg_img_h # handle two cases. Embedded and linked images # <image .. xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAT8AA ..." preserveAspectRatio="none" height="432" width="425" transform="matrix(1,0,-0.52013328,0.85408511,0,0)"/> # <image .. xlink:href="xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgAB..." # <image .. xlink:href="file:///home/jw/schaf.png" href=str(node.get(inkex.addNS('href','xlink'))) # ###################### # # dump the entire svg to file, so that we can examine what an image is. # f=open(self.dumpname, 'w') # f.write(href) # f.close() # if debug: print >>self.tty, "Dump written to "+self.dumpname # # ###################### if href[:7] == 'file://': filename=href[7:] if debug: print >>self.tty, "linked image: ="+filename elif href[0] == '/' or href[0] == '.': filename=href if debug: print >>self.tty, "linked image path: ="+filename elif href[:11] == 'data:image/': l = href[11:].index(';') type = href[11:11+l] # 'png' 'jpeg' if debug: print >>self.tty, "embedded image: "+href[:11+l] img=base64.decodestring(href[11+l+8:]) f=tempfile.NamedTemporaryFile(mode="wb", prefix='centerlinetrace', suffix="."+type, delete=False) f.write(img) filename=f.name f.close() else: inkex.errormsg(_("Neither file:// nor data:image/; prefix. Cannot parse PNG/JPEG image href "+href[:200]+"...")) sys.exit(1) if debug: print >>self.tty, "filename="+filename # path_svg,stroke_width,im_size = self.svg_centerline_trace(filename, cliprect) xml = inkex.etree.fromstring(path_svg) try: path_d=xml.find('path').attrib['d'] except: inkex.errormsg(_("Couldn't trace the path. Please make sure that the checkbox for tracing bright lines is set correctly and that your drawing has enough contrast.")) sys.exit(1) sx = svg_img_w/im_size[0] sy = svg_img_h/im_size[1] if debug: print >>self.tty, "svg_im_width ", svg_img_w, "sx=",sx if debug: print >>self.tty, "svg_im_height ", svg_img_h, "sy=",sy if debug: print >>self.tty, "im_x ", svg_x_off if debug: print >>self.tty, "im_y ", svg_y_off if debug: print >>self.tty, "pixel_size= ", im_size ## map the coordinates of the returned pixel path to the coordinates of the original SVG image. if cliprect is not None: svg_x_off = max(svg_x_off, float(cliprect['node'].get('x', 0))) svg_y_off = max(svg_y_off, float(cliprect['node'].get('y', 0))) matrix = "translate(%g,%g) scale(%g,%g)" % (svg_x_off, svg_y_off, sx, sy) # if href[:5] == 'data:': os.unlink(filename) ## it was a temporary file (representing an embedded image). # # Create SVG Path if self.hairline: stroke_width = self.hairline_width * 96. / 25.4 # mm2px FIXME: 96dpi is just a default guess. else: stroke_width = stroke_width * 0.5 * (abs(sx) + abs(sy)) style = { 'stroke': '#000000', 'fill': 'none', 'stroke-linecap': 'round', 'stroke-width': stroke_width } if self.invert_image: style['stroke'] = '#777777' path_attr = { 'style': simplestyle.formatStyle(style), 'd': path_d, 'transform': matrix } ## insert the new path object inkex.etree.SubElement(self.current_layer, inkex.addNS('path', 'svg'), path_attr) ## delete the old image object if self.replace_image: node.getparent().remove(node) if cliprect is not None: # and its cliprect ... cliprect['node'].getparent().remove(cliprect['node'])
def draw_SVG_line(x1, y1, x2, y2, width, name, parent): style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill': 'none' } line_attribs = {'style':simplestyle.formatStyle(style), inkex.addNS('label','inkscape'):name, 'd':'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)} inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs )
'M ' + str(p1[0]) + ',' + str(p1[1]) + ' L ' + str(p2[0]) + ',' + str(p2[1]) + ' L ' + str(p3[0]) + ',' + str(p3[1]) + ' L ' + str(p1[0]) + ',' + str(p1[1]) + ' z' } inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), tri_attribs) #draw an SVG line segment between the given (raw) points def draw_SVG_line((x1, y1), (x2, y2), style, name, parent): line_style = { 'stroke': style.l_col, 'stroke-width': str(style.l_th), 'fill': style.l_fill } line_attribs = { 'style': simplestyle.formatStyle(line_style), inkex.addNS('label', 'inkscape'): name, 'd': 'M ' + str(x1) + ',' + str(y1) + ' L ' + str(x2) + ',' + str(y2) } inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) #lines from each vertex to a corresponding point in trilinears def draw_vertex_lines(vert_mat, params, width, name, parent): for i in range(3): oppositepoint = get_cartesian_pt(vert_mat[i], params) draw_SVG_line(params[3][-i % 3], oppositepoint, width, name + ':' + str(i), parent) #MATHEMATICAL ROUTINES
def effect(self): svg = self.document.getroot() # create new layers for dots and for numbers dotLayer = inkex.etree.SubElement(svg, 'g') dotLayer.set(inkex.addNS('label', 'inkscape'), 'ConnectTheDots dotLayer') dotLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') numberLayer = inkex.etree.SubElement(svg, 'g') numberLayer.set(inkex.addNS('label', 'inkscape'), 'ConnectTheDots numberLayer') numberLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') min_dist = float(self.options.dist) # iterate over every path, start numbering from 1 every time for id, path in self.selected.iteritems(): if path.tag == 'path' or path.tag == inkex.addNS('path', 'svg'): # radius and fontsize as offsets to avoid placing numbers inside dots r = float(self.options.radius) f = 0.5 * int(self.options.fontsize) # iterate over vertices and draw dots on each as well as the number next to it d = path.get('d') vertices = simplepath.parsePath(d) dist = 2 ^ 32 - 1 prev_x, prev_y = 0, 0 count_idx = 0 for idx, v in enumerate(vertices): x, y = self.getXY(v) if idx > 1: dist = sqrt((x - prev_x)**2 + (y - prev_y)**2) if (min_dist != -1): if (dist <= min_dist): prev_x, prev_y = x, y continue count_idx = count_idx + 1 # create dots style = { 'stroke': 'none', 'stroke-width': '0', 'fill': '#000000' } name = 'pbn_%i' % count_idx attributes = { 'style': simplestyle.formatStyle(style), inkex.addNS('cx', 'sodipodi'): str(x), inkex.addNS('cy', 'sodipodi'): str(y), inkex.addNS('rx', 'sodipodi'): self.options.radius, inkex.addNS('ry', 'sodipodi'): self.options.radius, inkex.addNS('start', 'sodipodi'): str(0), inkex.addNS('end', 'sodipodi'): str(2 * pi), inkex.addNS('open', 'sodipodi'): 'false', inkex.addNS('type', 'sodipodi'): 'arc', inkex.addNS('label', 'inkscape'): name } dot = inkex.etree.SubElement(dotLayer, inkex.addNS('path', 'svg'), attributes) if idx > 0 and idx < len(vertices) - 1: # block two quadrants, one for the previous and one for the next freeQuads = self.findFreeQuadrants( (x, y), self.getXY(vertices[idx - 1]), self.getXY(vertices[idx + 1])) else: # special case for end nodes, only block one quadrant freeQuads = self.findFreeQuadrants( (x, y), self.getXY(vertices[idx - 1])) # randomly place number in one of the free quadrants q = choice(freeQuads) if q == self.TOP_RIGHT: nx = x + 2 * r ny = y + 2 * r + f textAnchor = 'start' elif q == self.TOP_LEFT: nx = x - 2 * r ny = y + r + f textAnchor = 'end' elif q == self.BOTTOM_LEFT: nx = x - r ny = y - r textAnchor = 'end' else: # BOTTOM_RIGHT nx = x + r ny = y - r textAnchor = 'start' # create the number element number = inkex.etree.Element(inkex.addNS('text', 'svg')) number.text = str(count_idx) number.set('x', str(nx)) number.set('y', str(ny)) number.set('font-size', self.options.fontsize) number.set('text-anchor', textAnchor) numberLayer.append(number) # update previous point prev_x, prev_y = x, y # hide the original path if specified in options if self.options.hidepath == 'true': path.set('display', 'none')
def draw_SVG_rect(x,y,w,h, width, fill, name, parent): style = { 'stroke': '#000000', 'stroke-width':str(width), 'fill':fill} rect_attribs = {'style':simplestyle.formatStyle(style), inkex.addNS('label','inkscape'):name, 'x':str(x), 'y':str(y), 'width':str(w), 'height':str(h)} inkex.etree.SubElement(parent, inkex.addNS('rect','svg'), rect_attribs )
#!/usr/bin/env python # coding: utf8 # We will use the inkex module with the predefined Effect base class. import inkex # The simplestyle module provides functions for style parsing. import simplestyle import math objStyle = simplestyle.formatStyle({ 'stroke': '#000000', 'stroke-width': 0.1, 'fill': 'none' }) class inkcape_path: def __init__(self, Offset, group, Label=None): self.offsetX = Offset[0] self.offsetY = Offset[1] self.Path = '' self.group = group self.Label = Label def MoveTo(self, x, y): #Return string 'M X Y' where X and Y are updated values from parameters self.Path += ' M ' + str(round(x - self.offsetX, 3)) + ',' + str( round(y - self.offsetY, 3)) def LineTo(self, x, y): #Return string 'L X Y' where X and Y are updated values from parameters
def effect(self): """ Calculate Gear factors from inputs. - Make list of radii, angles, and centers for each tooth and iterate through them - Turn on other visual features e.g. cross, rack, annotations, etc """ # check for correct number of selected objects and return a translatable errormessage to the user if len(self.options.ids) != 2: inkex.errormsg(_("This extension requires two selected objects.")) exit() # Convert color - which comes in as a long into a string like '#FFFFFF' self.options.strokeColour = self.getColorString( self.options.strokeColour) # path_stroke = self.options.strokeColour # take color from tab3 path_fill = 'none' # no fill - just a line path_stroke_width = 0.6 # can also be in form '0.6mm' # gather incoming params and convert param1 = self.options.param1 param2 = self.options.param2 param3 = self.options.param3 choice = self.options.achoice units2 = self.options.units2 accuracy = self.options.accuracy # although a string in inx - option parser converts to int. # calculate unit factor for units defined in dialog. unit_factor = self.calc_unit_factor() # what page are we on page_id = self.options.active_tab # sometimes wrong the very first time # Do your thing - create some points or a path or whatever... points = [] points.extend([(i * 2, i * 2) for i in range(0, param1)]) points.append((param1, param1 * 2 + 5)) #inkex.debug(points) path = points_to_svgd(points) #inkex.debug(path) bbox_center = points_to_bbox_center(points) # example debug # print >>self.tty, bbox_center # or # inkex.debug("bbox center %s" % bbox_center) # Embed the path in a group to make animation easier: # Be sure to examine the internal structure by looking in the xml editor inside inkscape # This finds center of exisiting document page # This finds center of current view in inkscape t = 'translate(%s,%s)' % (self.view_center[0], self.view_center[1]) # Make a nice useful name g_attribs = { inkex.addNS('label', 'inkscape'): 'useful name' + str(param1), inkex.addNS('transform-center-x', 'inkscape'): str(-bbox_center[0]), inkex.addNS('transform-center-y', 'inkscape'): str(-bbox_center[1]), 'transform': t, 'info': 'N: ' + str(param1) + '; with:' + str(param2) } # add the group to the document's current layer topgroup = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) # Create SVG Path under this top level group # define style using basic dictionary style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': param2 } # convert style into svg form (see import at top of file) mypath_attribs = {'style': simplestyle.formatStyle(style), 'd': path} # add path to scene squiggle = inkex.etree.SubElement(topgroup, inkex.addNS('path', 'svg'), mypath_attribs) # Add another feature in same group (under it) style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': path_stroke_width } cs = param1 / 2 # centercross length cs2 = str(cs) d = 'M-' + cs2 + ',0L' + cs2 + ',0M0,-' + cs2 + 'L0,' + cs2 # 'M-10,0L10,0M0,-10L0,10' # or d = 'M %s,0 L %s,0 M 0,-%s L 0,%s' % (-cs, cs, cs, cs) # or d = 'M {0},0 L {1},0 M 0,{0} L 0,{1}'.format(-cs, cs) # or #d = 'M-10 0L10 0M0 -10L0 10' # commas superfluous, minimise spaces. cross_attribs = { inkex.addNS('label', 'inkscape'): 'Center cross', 'style': simplestyle.formatStyle(style), 'd': d } cross = inkex.etree.SubElement(topgroup, inkex.addNS('path', 'svg'), cross_attribs) # Add a precalculated svg circle style = { 'stroke': path_stroke, 'fill': path_fill, 'stroke-width': self.getUnittouu(str(param2) + self.options.units) } draw_SVG_circle(topgroup, param1 * 4 * unit_factor, 0, 0, 'a circle', style) # Add some super basic text (e.g. for debug) if choice: notes = [ 'a label: %d (%s) ' % (param1 * unit_factor, self.options.units), 'doc line' ] text_height = 12 # position above y = -22 for note in notes: self.add_text(topgroup, note, [0, y], text_height) y += text_height * 1.2 # #more complex text font_height = min( 32, max(10, int(self.getUnittouu(str(param1) + self.options.units)))) text_style = { 'font-size': str(font_height), 'font-family': 'arial', 'text-anchor': 'middle', 'text-align': 'center', 'fill': path_stroke } text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': str(44), 'y': str(-15) } text = inkex.etree.SubElement(topgroup, 'text', text_atts) text.text = "%4.3f" % (param1 * param2)
import inkex import simplestyle from math import * from collections import namedtuple #Note: keep in mind that SVG coordinates start in the top-left corner i.e. with an inverted y-axis errormsg = inkex.errormsg debug = inkex.debug default_style = simplestyle.formatStyle( {'stroke': '#000000', 'stroke-width': '1', 'fill': 'none' }) groove_style = simplestyle.formatStyle( {'stroke': '#0000FF', 'stroke-width': '1', 'fill': 'none' }) mark_style = simplestyle.formatStyle( {'stroke': '#00FF00', 'stroke-width': '1', 'fill': 'none' })
if block != defs: # in a BLOCK layer = block elif vals[groups['8']]: # use Common Layer Name if not vals[groups['8']][0]: vals[groups['8']][0] = '0' # use default name layer = layer_nodes[vals[groups['8']][0]] color = '#000000' # default color if vals[groups['8']]: if layer_colors.has_key(vals[groups['8']][0]): if colors.has_key(layer_colors[vals[groups['8']][0]]): color = colors[layer_colors[vals[groups['8']][0]]] if vals[groups['62']]: # Common Color Number if colors.has_key(vals[groups['62']][0]): color = colors[vals[groups['62']][0]] style = simplestyle.formatStyle({ 'stroke': '%s' % color, 'fill': 'none' }) w = 0.5 # default lineweight for POINT if vals[groups['370']]: # Common Lineweight if vals[groups['370']][0] > 0: w = 96.0 / 25.4 * vals[groups['370']][0] / 100.0 if w < 0.5: w = 0.5 style = simplestyle.formatStyle({ 'stroke': '%s' % color, 'fill': 'none', 'stroke-width': '%.1f' % w }) if vals[groups['6']]: # Common Linetype if linetypes.has_key(vals[groups['6']][0]): style += ';' + linetypes[vals[groups['6']][0]]
def effect(self): self.options.primaryr = self.unittouu( str(self.options.primaryr) + 'px') self.options.secondaryr = self.unittouu( str(self.options.secondaryr) + 'px') self.options.penr = self.unittouu(str(self.options.penr) + 'px') if self.options.secondaryr == 0: return if self.options.quality == 0: return if (self.options.gearplacement.strip(' ').lower().startswith('outside') ): a = self.options.primaryr + self.options.secondaryr flip = -1 else: a = self.options.primaryr - self.options.secondaryr flip = 1 ratio = a / self.options.secondaryr if ratio == 0: return scale = 2 * math.pi / (ratio * self.options.quality) rotation = -math.pi * self.options.rotation / 180 new = inkex.etree.Element(inkex.addNS('path', 'svg')) s = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) } new.set('style', simplestyle.formatStyle(s)) pathString = '' maxPointCount = 1000 for i in range(maxPointCount): theta = i * scale view_center = computePointInNode(list(self.view_center), self.current_layer) x = a * math.cos(theta + rotation) + \ self.options.penr * math.cos(ratio * theta + rotation) * flip + \ view_center[0] y = a * math.sin(theta + rotation) - \ self.options.penr * math.sin(ratio * theta + rotation) + \ view_center[1] dx = (-a * math.sin(theta + rotation) - \ ratio * self.options.penr * math.sin(ratio * theta + rotation) * flip) * scale / 3 dy = (a * math.cos(theta + rotation) - \ ratio * self.options.penr * math.cos(ratio * theta + rotation)) * scale / 3 if i <= 0: pathString += 'M ' + str(x) + ',' + str(y) + ' C ' + str( x + dx) + ',' + str(y + dy) + ' ' else: pathString += str(x - dx) + ',' + str(y - dy) + ' ' + str( x) + ',' + str(y) if math.fmod(i / ratio, self.options.quality ) == 0 and i % self.options.quality == 0: pathString += 'Z' break else: if i == maxPointCount - 1: pass # we reached the allowed maximum of points, stop here else: pathString += ' C ' + str(x + dx) + ',' + str(y + dy) + ' ' new.set('d', pathString) self.current_layer.append(new)
def set_style(node, style): ''' Sugar coated way to set the style dict, for node ''' node.attrib['style'] = simplestyle.formatStyle(style)
def propagate_attribs(node, parent_style={}, parent_transform=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): """Propagate style and transform to remove inheritance""" # Don't enter non-graphical portions of the document if (node.tag == addNS("namedview", "sodipodi") or node.tag == addNS("defs", "svg") or node.tag == addNS("metadata", "svg") or node.tag == addNS("foreignObject", "svg")): return # Compose the transformations if node.tag == addNS("svg", "svg") and node.get("viewBox"): vx, vy, vw, vh = [ get_dimension(x) for x in node.get("viewBox").split() ] dw = get_dimension(node.get("width", vw)) dh = get_dimension(node.get("height", vh)) t = "translate(%f, %f) scale(%f, %f)" % (-vx, -vy, dw / vw, dh / vh) this_transform = simpletransform.parseTransform(t, parent_transform) this_transform = simpletransform.parseTransform( node.get("transform"), this_transform) del node.attrib["viewBox"] else: this_transform = simpletransform.parseTransform( node.get("transform"), parent_transform) # Compose the style attribs this_style = simplestyle.parseStyle(node.get("style", "")) remaining_style = {} # Style attributes that are not propagated non_propagated = ["filter" ] # Filters should remain on the topmost ancestor for key in non_propagated: if key in this_style.keys(): remaining_style[key] = this_style[key] del this_style[key] # Create a copy of the parent style, and merge this style into it parent_style_copy = parent_style.copy() parent_style_copy.update(this_style) this_style = parent_style_copy # Merge in any attributes outside of the style style_attribs = ["fill", "stroke"] for attrib in style_attribs: if node.get(attrib): this_style[attrib] = node.get(attrib) del node.attrib[attrib] if (node.tag == addNS("svg", "svg") or node.tag == addNS("g", "svg") or node.tag == addNS("a", "svg") or node.tag == addNS("switch", "svg")): # Leave only non-propagating style attributes if len(remaining_style) == 0: if "style" in node.keys(): del node.attrib["style"] else: node.set("style", simplestyle.formatStyle(remaining_style)) # Remove the transform attribute if "transform" in node.keys(): del node.attrib["transform"] # Continue propagating on subelements for c in node.iterchildren(): propagate_attribs(c, this_style, this_transform) else: # This element is not a container # Merge remaining_style into this_style this_style.update(remaining_style) # Set the element's style and transform attribs node.set("style", simplestyle.formatStyle(this_style)) node.set("transform", simpletransform.formatTransform(this_transform))
def effect(self): if not self.options.ids: inkex.errormsg(_("Please select an object")) exit() scale = self.unittouu('1px') # convert to document units self.options.size *= scale self.options.border *= scale q = { 'x': 0, 'y': 0, 'width': 0, 'height': 0 } # query the bounding box of ids[0] for query in q.keys(): p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query, self.options.ids[0], self.args[-1]), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = scale * float(p.stdout.read()) mat = simpletransform.composeParents( self.selected[self.options.ids[0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) defs = self.xpathSingle('/svg:svg//svg:defs') pattern = inkex.etree.SubElement(defs, inkex.addNS('pattern', 'svg')) pattern.set('id', 'Voronoi' + str(random.randint(1, 9999))) pattern.set('width', str(q['width'])) pattern.set('height', str(q['height'])) pattern.set( 'patternTransform', 'translate(%s,%s)' % (q['x'] - mat[0][2], q['y'] - mat[1][2])) pattern.set('patternUnits', 'userSpaceOnUse') # generate random pattern of points c = voronoi.Context() pts = [] b = float(self.options.border) # width of border for i in range( int(q['width'] * q['height'] / self.options.size / self.options.size)): x = random.random() * q['width'] y = random.random() * q['height'] if b > 0: # duplicate border area pts.append(voronoi.Site(x, y)) if x < b: pts.append(voronoi.Site(x + q['width'], y)) if y < b: pts.append( voronoi.Site(x + q['width'], y + q['height'])) if y > q['height'] - b: pts.append( voronoi.Site(x + q['width'], y - q['height'])) if x > q['width'] - b: pts.append(voronoi.Site(x - q['width'], y)) if y < b: pts.append( voronoi.Site(x - q['width'], y + q['height'])) if y > q['height'] - b: pts.append( voronoi.Site(x - q['width'], y - q['height'])) if y < b: pts.append(voronoi.Site(x, y + q['height'])) if y > q['height'] - b: pts.append(voronoi.Site(x, y - q['height'])) elif x > -b and y > -b and x < q['width'] + b and y < q[ 'height'] + b: pts.append(voronoi.Site(x, y)) # leave border area blank # dot = inkex.etree.SubElement(pattern, inkex.addNS('rect','svg')) # dot.set('x', str(x-1)) # dot.set('y', str(y-1)) # dot.set('width', '2') # dot.set('height', '2') if len(pts) < 3: inkex.errormsg( "Please choose a larger object, or smaller cell size") exit() # plot Voronoi diagram sl = voronoi.SiteList(pts) voronoi.voronoi(sl, c) path = "" for edge in c.edges: if edge[1] >= 0 and edge[2] >= 0: # two vertices [x1, y1, x2, y2 ] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], c.vertices[edge[2]][0], c.vertices[edge[2]][1], q['width'], q['height']) elif edge[1] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0] if c.vertices[edge[1]][1] > q['height'] / 2: ytemp = q['height'] else: ytemp = 0 else: xtemp = q['width'] ytemp = (c.lines[edge[0]][2] - q['width'] * c.lines[edge[0]][0]) / c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], xtemp, ytemp, q['width'], q['height']) elif edge[2] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0] if c.vertices[edge[2]][1] > q['height'] / 2: ytemp = q['height'] else: ytemp = 0 else: xtemp = 0 ytemp = c.lines[edge[0]][2] / c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(xtemp, ytemp, c.vertices[edge[2]][0], c.vertices[edge[2]][1], q['width'], q['height']) if x1 or x2 or y1 or y2: path += 'M %.3f,%.3f %.3f,%.3f ' % (x1, y1, x2, y2) patternstyle = {'stroke': '#000000', 'stroke-width': str(scale)} attribs = {'d': path, 'style': simplestyle.formatStyle(patternstyle)} inkex.etree.SubElement(pattern, inkex.addNS('path', 'svg'), attribs) # link selected object to pattern obj = self.selected[self.options.ids[0]] style = {} if obj.attrib.has_key('style'): style = simplestyle.parseStyle(obj.attrib['style']) style['fill'] = 'url(#%s)' % pattern.get('id') obj.attrib['style'] = simplestyle.formatStyle(style) if obj.tag == inkex.addNS('g', 'svg'): for node in obj: style = {} if node.attrib.has_key('style'): style = simplestyle.parseStyle(node.attrib['style']) style['fill'] = 'url(#%s)' % pattern.get('id') node.attrib['style'] = simplestyle.formatStyle(style)
def recursiveFuseTransform(self, node, transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): transf = composeTransform(transf, parseTransform(node.get("transform", None))) if 'transform' in node.attrib: del node.attrib['transform'] if 'style' in node.attrib: style = node.attrib.get('style') style = simplestyle.parseStyle(style) update = False if 'stroke-width' in style: try: stroke_width = self.unittouu( style.get('stroke-width').strip()) # pixelsnap ext assumes scaling is similar in x and y # and uses the x scale... # let's try to be a bit smarter stroke_width *= math.sqrt(transf[0][0]**2 + transf[1][1]**2) style['stroke-width'] = str(stroke_width) update = True except AttributeError: pass if update: style = simplestyle.formatStyle(style) node.attrib['style'] = style node = ApplyTransform.objectToPath(node) if 'd' in node.attrib: d = node.get('d') p = cubicsuperpath.parsePath(d) applyTransformToPath(transf, p) node.set('d', cubicsuperpath.formatPath(p)) elif node.tag in [ inkex.addNS('polygon', 'svg'), inkex.addNS('polyline', 'svg') ]: points = node.get('points') points = points.strip().split(' ') for k, p in enumerate(points): if ',' in p: p = p.split(',') p = [float(p[0]), float(p[1])] applyTransformToPoint(transf, p) p = [str(p[0]), str(p[1])] p = ','.join(p) points[k] = p points = ' '.join(points) node.set('points', points) elif node.tag in [ inkex.addNS('rect', 'svg'), inkex.addNS('text', 'svg'), inkex.addNS('image', 'svg'), inkex.addNS('use', 'svg'), inkex.addNS('circle', 'svg') ]: node.set('transform', formatTransform(transf)) for child in node.getchildren(): self.recursiveFuseTransform(child, transf)
def effect(self): exponent = self.options.exponent if exponent>= 0: exponent = 1.0 + exponent else: exponent = 1.0/(1.0 - exponent) steps = [1.0/(self.options.steps + 1.0)] for i in range(self.options.steps - 1): steps.append(steps[0] + steps[-1]) steps = [step**exponent for step in steps] paths = {} styles = {} for id in self.options.ids: node = self.selected[id] if node.tag ==inkex.addNS('path','svg'): paths[id] = cubicsuperpath.parsePath(node.get('d')) styles[id] = simplestyle.parseStyle(node.get('style')) trans = node.get('transform') if trans: simpletransform.applyTransformToPath(simpletransform.parseTransform(trans), paths[id]) else: self.options.ids.remove(id) for i in range(1,len(self.options.ids)): start = copy.deepcopy(paths[self.options.ids[i-1]]) end = copy.deepcopy(paths[self.options.ids[i]]) sst = copy.deepcopy(styles[self.options.ids[i-1]]) est = copy.deepcopy(styles[self.options.ids[i]]) basestyle = copy.deepcopy(sst) if basestyle.has_key('stroke-width'): basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,0) #prepare for experimental style tweening if self.options.style: dostroke = True dofill = True styledefaults = {'opacity':'1.0', 'stroke-opacity':'1.0', 'fill-opacity':'1.0', 'stroke-width':'1.0', 'stroke':'none', 'fill':'none'} for key in styledefaults.keys(): sst.setdefault(key,styledefaults[key]) est.setdefault(key,styledefaults[key]) isnotplain = lambda x: not (x=='none' or x[:1]=='#') if isnotplain(sst['stroke']) or isnotplain(est['stroke']) or (sst['stroke']=='none' and est['stroke']=='none'): dostroke = False if isnotplain(sst['fill']) or isnotplain(est['fill']) or (sst['fill']=='none' and est['fill']=='none'): dofill = False if dostroke: if sst['stroke']=='none': sst['stroke-width'] = '0.0' sst['stroke-opacity'] = '0.0' sst['stroke'] = est['stroke'] elif est['stroke']=='none': est['stroke-width'] = '0.0' est['stroke-opacity'] = '0.0' est['stroke'] = sst['stroke'] if dofill: if sst['fill']=='none': sst['fill-opacity'] = '0.0' sst['fill'] = est['fill'] elif est['fill']=='none': est['fill-opacity'] = '0.0' est['fill'] = sst['fill'] if self.options.method == 2: #subdivide both paths into segments of relatively equal lengths slengths, stotal = csplength(start) elengths, etotal = csplength(end) lengths = {} t = 0 for sp in slengths: for l in sp: t += l / stotal lengths.setdefault(t,0) lengths[t] += 1 t = 0 for sp in elengths: for l in sp: t += l / etotal lengths.setdefault(t,0) lengths[t] += -1 sadd = [k for (k,v) in lengths.iteritems() if v < 0] sadd.sort() eadd = [k for (k,v) in lengths.iteritems() if v > 0] eadd.sort() t = 0 s = [[]] for sp in slengths: if not start[0]: s.append(start.pop(0)) s[-1].append(start[0].pop(0)) for l in sp: pt = t t += l / stotal if sadd and t > sadd[0]: while sadd and sadd[0] < t: nt = (sadd[0] - pt) / (t - pt) bezes = cspbezsplitatlength(s[-1][-1][:],start[0][0][:], nt) s[-1][-1:] = bezes[:2] start[0][0] = bezes[2] pt = sadd.pop(0) s[-1].append(start[0].pop(0)) t = 0 e = [[]] for sp in elengths: if not end[0]: e.append(end.pop(0)) e[-1].append(end[0].pop(0)) for l in sp: pt = t t += l / etotal if eadd and t > eadd[0]: while eadd and eadd[0] < t: nt = (eadd[0] - pt) / (t - pt) bezes = cspbezsplitatlength(e[-1][-1][:],end[0][0][:], nt) e[-1][-1:] = bezes[:2] end[0][0] = bezes[2] pt = eadd.pop(0) e[-1].append(end[0].pop(0)) start = s[:] end = e[:] else: #which path has fewer segments? lengthdiff = numsegs(start) - numsegs(end) #swap shortest first if lengthdiff > 0: start, end = end, start #subdivide the shorter path for x in range(abs(lengthdiff)): maxlen = 0 subpath = 0 segment = 0 for y in range(len(start)): for z in range(1, len(start[y])): leng = bezlenapprx(start[y][z-1], start[y][z]) if leng > maxlen: maxlen = leng subpath = y segment = z sp1, sp2 = start[subpath][segment - 1:segment + 1] start[subpath][segment - 1:segment + 1] = cspbezsplit(sp1, sp2) #if swapped, swap them back if lengthdiff > 0: start, end = end, start #break paths so that corresponding subpaths have an equal number of segments s = [[]] e = [[]] while start and end: if start[0] and end[0]: s[-1].append(start[0].pop(0)) e[-1].append(end[0].pop(0)) elif end[0]: s.append(start.pop(0)) e[-1].append(end[0][0]) e.append([end[0].pop(0)]) elif start[0]: e.append(end.pop(0)) s[-1].append(start[0][0]) s.append([start[0].pop(0)]) else: s.append(start.pop(0)) e.append(end.pop(0)) if self.options.dup: steps = [0] + steps + [1] #create an interpolated path for each interval group = inkex.etree.SubElement(self.current_layer,inkex.addNS('g','svg')) for time in steps: interp = [] #process subpaths for ssp,esp in zip(s, e): if not (ssp or esp): break interp.append([]) #process superpoints for sp,ep in zip(ssp, esp): if not (sp or ep): break interp[-1].append([]) #process points for p1,p2 in zip(sp, ep): if not (sp or ep): break interp[-1][-1].append(interppoints(p1, p2, time)) #remove final subpath if empty. if not interp[-1]: del interp[-1] #basic style tweening if self.options.style: basestyle['opacity'] = tweenstylefloat('opacity',sst,est,time) if dostroke: basestyle['stroke-opacity'] = tweenstylefloat('stroke-opacity',sst,est,time) basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,time) basestyle['stroke'] = tweenstylecolor('stroke',sst,est,time) if dofill: basestyle['fill-opacity'] = tweenstylefloat('fill-opacity',sst,est,time) basestyle['fill'] = tweenstylecolor('fill',sst,est,time) attribs = {'style':simplestyle.formatStyle(basestyle),'d':cubicsuperpath.formatPath(interp)} new = inkex.etree.SubElement(group,inkex.addNS('path','svg'), attribs)
def effect(self): teeth = self.options.teeth pitch = self.unittouu( str(self.options.pitch) + self.options.unit) angle = self.options.angle # Angle of tangent to tooth at circular pitch wrt radial line. centerdiameter = self.unittouu( str(self.options.centerdiameter) + self.options.unit) # print >>sys.stderr, "Teeth: %s\n" % teeth two_pi = 2.0 * pi # Pitch (circular pitch): Length of the arc from one tooth to the next) # Pitch diameter: Diameter of pitch circle. pitch_diameter = float( teeth ) * pitch / pi pitch_radius = pitch_diameter / 2.0 # Base Circle base_diameter = pitch_diameter * cos( radians( angle ) ) base_radius = base_diameter / 2.0 # Diametrial pitch: Number of teeth per unit length. pitch_diametrial = float( teeth )/ pitch_diameter # Addendum: Radial distance from pitch circle to outside circle. addendum = 1.0 / pitch_diametrial # Outer Circle outer_radius = pitch_radius + addendum outer_diameter = outer_radius * 2.0 # Tooth thickness: Tooth width along pitch circle. tooth = ( pi * pitch_diameter ) / ( 2.0 * float( teeth ) ) # Undercut? undercut = (2.0 / ( sin( radians( angle ) ) ** 2)) needs_undercut = teeth < undercut # Clearance: Radial distance between top of tooth on one gear to bottom of gap on another. clearance = 0.0 # Dedendum: Radial distance from pitch circle to root diameter. dedendum = addendum + clearance # Root diameter: Diameter of bottom of tooth spaces. root_radius = pitch_radius - dedendum root_diameter = root_radius * 2.0 half_thick_angle = two_pi / (4.0 * float( teeth ) ) pitch_to_base_angle = involute_intersect_angle( base_radius, pitch_radius ) pitch_to_outer_angle = involute_intersect_angle( base_radius, outer_radius ) - pitch_to_base_angle centers = [(x * two_pi / float( teeth) ) for x in range( teeth ) ] points = [] for c in centers: # Angles pitch1 = c - half_thick_angle base1 = pitch1 - pitch_to_base_angle outer1 = pitch1 + pitch_to_outer_angle pitch2 = c + half_thick_angle base2 = pitch2 + pitch_to_base_angle outer2 = pitch2 - pitch_to_outer_angle # Points b1 = point_on_circle( base_radius, base1 ) p1 = point_on_circle( pitch_radius, pitch1 ) o1 = point_on_circle( outer_radius, outer1 ) b2 = point_on_circle( base_radius, base2 ) p2 = point_on_circle( pitch_radius, pitch2 ) o2 = point_on_circle( outer_radius, outer2 ) if root_radius > base_radius: pitch_to_root_angle = pitch_to_base_angle - involute_intersect_angle(base_radius, root_radius ) root1 = pitch1 - pitch_to_root_angle root2 = pitch2 + pitch_to_root_angle r1 = point_on_circle(root_radius, root1) r2 = point_on_circle(root_radius, root2) p_tmp = [r1,p1,o1,o2,p2,r2] else: r1 = point_on_circle(root_radius, base1) r2 = point_on_circle(root_radius, base2) p_tmp = [r1,b1,p1,o1,o2,p2,b2,r2] points.extend( p_tmp ) path = points_to_svgd( points ) # Embed gear in group to make animation easier: # Translate group, Rotate path. view_center = computePointInNode(list(self.view_center), self.current_layer) t = 'translate(' + str( view_center[0] ) + ',' + str( view_center[1] ) + ')' g_attribs = {inkex.addNS('label','inkscape'):'Gear' + str( teeth ), 'transform':t } g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) # Create SVG Path for gear style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) } gear_attribs = {'style':simplestyle.formatStyle(style), 'd':path} gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs ) if(centerdiameter > 0.0): center_attribs = {'style':simplestyle.formatStyle(style), inkex.addNS('cx','sodipodi') :'0.0', inkex.addNS('cy','sodipodi') :'0.0', inkex.addNS('rx','sodipodi') :str(centerdiameter/2), inkex.addNS('ry','sodipodi') :str(centerdiameter/2), inkex.addNS('type','sodipodi') :'arc' } center = inkex.etree.SubElement(g, inkex.addNS('path','svg'), center_attribs )
def effect(self): # Get access to main SVG document element and get its dimensions. svg = self.document.getroot() # getting the parent tag of the guide nv = self.document.xpath('/svg:svg/sodipodi:namedview', namespaces=inkex.NSS)[0] documentUnits = inkex.addNS('document-units', 'inkscape') # print >> sys.stderr, nv.get(documentUnits) uunits = nv.get(documentUnits) message = "Units=" + uunits inkex.debug(message) # Get script's options value. stripwidth = self.unittouu(str(self.options.width) + uunits) striplength = self.unittouu(str(self.options.length) + uunits) cellheight = self.unittouu(str(self.options.cellheight) + uunits) cellwidth = self.unittouu(str(self.options.cellwidth) + uunits) scalecells = (self.options.scalecells) cellnumx = (self.options.cellnumx) cellnumy = (self.options.cellnumy) notchdepth = self.unittouu(str(self.options.notchdepth) + uunits) notchwidth = self.unittouu(str(self.options.notchwidth) + uunits) notchhorizontal = (self.options.notchhorizontal) notchvertical = (self.options.notchvertical) # notch2depth=self.unittouu(str(self.options.notch2depth)+uunits) notch2width = self.unittouu(str(self.options.notch2width) + uunits) notch2depth = stripwidth / 2 notchxcorner = (self.options.notchxcorner) notchycorner = (self.options.notchycorner) if scalecells: cellwidth = (striplength - 4 * notch2width) / cellnumx cellheight = (striplength - 4 * notch2width) / cellnumy notchxcorner = False notchycorner = False linewidth = self.unittouu(str(0.01) + uunits) distx = (striplength - cellnumx * cellwidth) / 2 disty = (striplength - cellnumy * cellheight) / 2 celldistx = (cellwidth - notchwidth) / 2 celldisty = (cellheight - notch2width) / 2 # getting the width and height attributes of the canvas width = float(self.unittouu(svg.attrib['width'])) height = float(self.unittouu(svg.attrib['height'])) # maxlength=max(width,height) # if striplength > maxlength: # factor=striplength/maxlength+1 inkex.debug("document width=" + str(self.uutounit(width, uunits))) inkex.debug("document height=" + str(self.uutounit(height, uunits))) inkex.debug("strip length=" + str(self.uutounit(striplength, uunits))) inkex.debug("strip width=" + str(self.uutounit(stripwidth, uunits))) inkex.debug("cell width=" + str(self.uutounit(cellwidth, uunits))) inkex.debug("cell height=" + str(self.uutounit(cellheight, uunits))) inkex.debug("Number of cells horizontal=" + str(cellnumx)) inkex.debug("Number of cells vertical =" + str(cellnumy)) inkex.debug("Depth of extra notch=" + str(self.uutounit(notchdepth, uunits))) inkex.debug("Width of extra notch=" + str(self.uutounit(notchwidth, uunits))) inkex.debug("Depth of notch for grid=" + str(self.uutounit(notchdepth, uunits))) inkex.debug("Width of notch for grid=" + str(self.uutounit(notchwidth, uunits))) inkex.debug("distx=" + str(self.uutounit(distx, uunits))) inkex.debug("disty=" + str(self.uutounit(disty, uunits))) inkex.debug("celldistx=" + str(self.uutounit(celldistx, uunits))) inkex.debug("celldisty=" + str(self.uutounit(celldisty, uunits))) parent = self.current_layer layername = '' if notchhorizontal: layername = layername + 'VLED ' if notchvertical: layername = layername + 'HLED ' # Create a new layer layer = inkex.etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), layername + 'Long strips') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') grp_name = 'group_horizontal_strip_long' grp_attribs = {inkex.addNS('label', 'inkscape'): grp_name} grp = inkex.etree.SubElement( layer, 'g', grp_attribs) #the group to put everything in style = { 'stroke': '#000000', 'stroke-width': str(linewidth), 'fill': 'none' } for num in range(0, 2): pathstring = 'M ' + str(1) + ',' + str(1) + ' L ' if notchxcorner: pathstring += str(stripwidth - 2 * notchdepth) + ',' + str( 1) # Obere Querkante pathstring += ' L ' + str(stripwidth - 2 * notchdepth) + ',' + str( notchwidth) # Erste Kerbe aussen pathstring += ' L ' + str(stripwidth) + ',' + str( notchwidth) # Ausrueckung else: pathstring += str(stripwidth) + ',' + str(1) if notchhorizontal: pathstring += ' L ' + str(stripwidth) + ',' + str( distx) # Distance to corner y = distx for i in range(0, cellnumx): pathstring += ' L ' + str(stripwidth) + ',' + str( y + celldistx) # Abstand pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + celldistx) # Einrueckung pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + celldistx + notchwidth) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + celldistx + notchwidth) # Ausrueckung pathstring += ' L ' + str(stripwidth) + ',' + str( y + 2 * celldistx + notchwidth) # Abstand y = y + 2 * celldistx + notchwidth if notchxcorner: pathstring += ' L ' + str(stripwidth) + ',' + str( striplength - notchwidth) # Untere rechte Ecke pathstring += ' L ' + str(stripwidth - 2 * notchdepth) + ',' + str( striplength - notchwidth) # Untere rechte Ecke pathstring += ' L ' + str( stripwidth - 2 * notchdepth) + ',' + str( striplength) # Untere rechte Ecke else: pathstring += ' L ' + str(stripwidth) + ',' + str(striplength) pathstring += ' L ' + str(1) + ',' + str( striplength) # Linke untere Ecke y = striplength - distx + notch2width / 2 pathstring += ' L ' + str(1) + ',' + str(y) # Distance to corner pathstring += ' L ' + str(notch2depth) + ',' + str( y) # Einrueckung for i in range(0, cellnumx): pathstring += ' L ' + str(notch2depth) + ',' + str( y - notch2width) # Kerbe pathstring += ' L ' + str(1) + ',' + str( y - notch2width) # Ausrueckung pathstring += ' L ' + str(1) + ',' + str( y - notch2width - cellwidth + notch2width) # Abstand pathstring += ' L ' + str(notch2depth) + ',' + str( y - notch2width - cellwidth + notch2width) # Einrueckung y = y - notch2width - cellwidth + notch2width pathstring += ' L ' + str(notch2depth) + ',' + str( y - notch2width) # Kerbe pathstring += ' L ' + str(1) + ',' + str( y - notch2width) # Ausrueckung pathstring += ' L ' + str(1) + ',' + str(1) + ' z' strip_transform = 'rotate(' + str(90) + ')' strip_transform += ' translate(' + str( stripwidth * num) + ',' + str(1) + ')' strip_attribs = { 'style': simplestyle.formatStyle(style), inkex.addNS('label', 'inkscape'): "strip horizontal long", 'transform': strip_transform, 'd': pathstring } inkex.etree.SubElement(grp, inkex.addNS('path', 'svg'), strip_attribs) celldisty = (cellheight - notch2width - notchwidth) / 2 grp_name = 'group_vertical_strip_long' grp_attribs = {inkex.addNS('label', 'inkscape'): grp_name} grp = inkex.etree.SubElement( layer, 'g', grp_attribs) #the group to put everything in for num in range(0, 2): y = disty - notch2width / 2 pathstring = 'M ' + str(1) + ',' + str(1) if notchycorner: pathstring += ' L ' + str(stripwidth - 2 * notchdepth) + ',' + str( 1) # Obere Querkante pathstring += ' L ' + str(stripwidth - 2 * notchdepth) + ',' + str(notchwidth) pathstring += ' L ' + str(stripwidth) + ',' + str(notchwidth) else: pathstring += ' L ' + str(stripwidth) + ',' + str(1) pathstring += ' L ' + str(stripwidth) + ',' + str( y) # Distance to corner for i in range(0, cellnumy): pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y) # Einrueckung pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y + notch2width) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width) # Ausrueckung if notchvertical: pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width + celldisty) # Abstand pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + notch2width + celldisty) # Einrueckung pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + notch2width + celldisty + notchwidth) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width + celldisty + notchwidth) # Ausrueckung pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width + 2 * celldisty + notchwidth) # Abstand y = y + notch2width + 2 * celldisty + notchwidth pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y) # Einrueckung pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y + notch2width) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width) # Ausrueckung if notchycorner: pathstring += ' L ' + str(stripwidth) + ',' + str( striplength - notchwidth) # Untere rechte Ecke pathstring += ' L ' + str(stripwidth - 2 * notchdepth) + ',' + str( striplength - notchwidth) # Untere rechte Ecke pathstring += ' L ' + str( stripwidth - 2 * notchdepth) + ',' + str( striplength) # Untere rechte Ecke else: pathstring += ' L ' + str(stripwidth) + ',' + str(striplength) pathstring += ' L ' + str(1) + ',' + str( striplength) # Linke untere Ecke pathstring += ' L ' + str(1) + ',' + str(1) + ' z' strip_transform = 'translate(' + str( num * stripwidth) + ',' + str(1) + ')' strip_attribs = { 'style': simplestyle.formatStyle(style), inkex.addNS('label', 'inkscape'): "strip vertical long", 'transform': strip_transform, 'd': pathstring } inkex.etree.SubElement(grp, inkex.addNS('path', 'svg'), strip_attribs) # Create a new layer layer = inkex.etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), layername + 'Horizontal strips short') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') grp_name = 'group horizontal_strip_short' grp_attribs = {inkex.addNS('label', 'inkscape'): grp_name} grp = inkex.etree.SubElement( layer, 'g', grp_attribs) #the group to put everything in striplength = cellnumx * cellwidth + 4 * notch2width distx = (striplength - cellnumx * cellwidth) / 2 disty = (striplength - cellnumy * cellheight) / 2 style = { 'stroke': '#000000', 'stroke-width': str(linewidth), 'fill': 'none' } for num in range(1, cellnumy): pathstring = 'M ' + str(1) + ',' + str(1) + ' L ' pathstring += str(stripwidth) + ',' + str(1) if notchhorizontal: pathstring += ' L ' + str(stripwidth) + ',' + str( distx) # Distance to corner y = distx for i in range(0, cellnumx): pathstring += ' L ' + str(stripwidth) + ',' + str( y + celldistx) # Abstand pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + celldistx) # Einrueckung pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + celldistx + notchwidth) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + celldistx + notchwidth) # Ausrueckung pathstring += ' L ' + str(stripwidth) + ',' + str( y + 2 * celldistx + notchwidth) # Abstand y = y + 2 * celldistx + notchwidth pathstring += ' L ' + str(stripwidth) + ',' + str(striplength) pathstring += ' L ' + str(1) + ',' + str( striplength) # Linke untere Ecke y = striplength - distx + notch2width / 2 pathstring += ' L ' + str(1) + ',' + str(y) # Distance to corner pathstring += ' L ' + str(notch2depth) + ',' + str( y) # Einrueckung for i in range(0, cellnumx): pathstring += ' L ' + str(notch2depth) + ',' + str( y - notch2width) # Kerbe pathstring += ' L ' + str(1) + ',' + str( y - notch2width) # Ausrueckung pathstring += ' L ' + str(1) + ',' + str( y - notch2width - cellwidth + notch2width) # Abstand pathstring += ' L ' + str(notch2depth) + ',' + str( y - notch2width - cellwidth + notch2width) # Einrueckung y = y - notch2width - cellwidth + notch2width pathstring += ' L ' + str(notch2depth) + ',' + str( y - notch2width) # Kerbe pathstring += ' L ' + str(1) + ',' + str( y - notch2width) # Ausrueckung pathstring += ' L ' + str(1) + ',' + str(1) + ' z' strip_transform = 'rotate(' + str(90) + ')' strip_transform += ' translate(' + str((num + 1) * stripwidth + 2) + ',' + str(1) + ')' stripname = "strip horizontal short" + str(num) strip_attribs = { 'style': simplestyle.formatStyle(style), inkex.addNS('label', 'inkscape'): stripname, 'transform': strip_transform, 'd': pathstring } inkex.etree.SubElement(grp, inkex.addNS('path', 'svg'), strip_attribs) # Create a new layer layer = inkex.etree.SubElement(svg, 'g') layer.set(inkex.addNS('label', 'inkscape'), layername + 'Vertical strips short') layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') grp_name = 'group vertical_strip_short' grp_attribs = {inkex.addNS('label', 'inkscape'): grp_name} grp = inkex.etree.SubElement( layer, 'g', grp_attribs) #the group to put everything in striplength = cellnumx * cellwidth + 4 * notch2width distx = (striplength - cellnumx * cellwidth) / 2 disty = (striplength - cellnumy * cellheight) / 2 striplength = cellnumy * cellheight + 4 * notch2width distx = (striplength - cellnumx * cellwidth) / 2 disty = (striplength - cellnumy * cellheight) / 2 celldisty = (cellheight - notch2width - notchwidth) / 2 for num in range(1, cellnumx): y = disty - notch2width / 2 pathstring = 'M ' + str(1) + ',' + str(1) pathstring += ' L ' + str(stripwidth) + ',' + str(1) pathstring += ' L ' + str(stripwidth) + ',' + str( y) # Distance to corner for i in range(0, cellnumy): pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y) # Einrueckung pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y + notch2width) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width) # Ausrueckung if notchvertical: pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width + celldisty) # Abstand pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + notch2width + celldisty) # Einrueckung pathstring += ' L ' + str(stripwidth - notchdepth) + ',' + str( y + notch2width + celldisty + notchwidth) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width + celldisty + notchwidth) # Ausrueckung pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width + 2 * celldisty + notchwidth) # Abstand y = y + notch2width + 2 * celldisty + notchwidth pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y) # Einrueckung pathstring += ' L ' + str(stripwidth - notch2depth) + ',' + str( y + notch2width) # Kerbe pathstring += ' L ' + str(stripwidth) + ',' + str( y + notch2width) # Ausrueckung pathstring += ' L ' + str(stripwidth) + ',' + str(striplength) pathstring += ' L ' + str(1) + ',' + str( striplength) # Linke untere Ecke pathstring += ' L ' + str(1) + ',' + str(1) + ' z' strip_transform = 'translate(' + str((num + 1) * stripwidth + 10) + ',' + str(1) + ')' stripname = "strip vertical short" + str(num) strip_attribs = { 'style': simplestyle.formatStyle(style), inkex.addNS('label', 'inkscape'): stripname, 'transform': strip_transform, 'd': pathstring } inkex.etree.SubElement(grp, inkex.addNS('path', 'svg'), strip_attribs)