def effect(self): zoom = self.unittouu(str(self.options.zoom) + 'px') if self.options.randomize: imagelist = generate_random_string(self.options.text, zoom) else: tokens = tokenize(self.options.text) imagelist = randomize_input_string(tokens, zoom) image = layoutstring(imagelist, zoom) if image: s = {'stroke': 'none', 'fill': '#000000'} new = inkex.etree.Element(inkex.addNS('path', 'svg')) new.set('style', simplestyle.formatStyle(s)) new.set('d', simplepath.formatPath(image)) self.current_layer.append(new) # compensate preserved transforms of parent layer if self.current_layer.getparent() is not None: mat = simpletransform.composeParents( self.current_layer, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) simpletransform.applyTransformToNode( simpletransform.invertTransform(mat), new)
def path_to_segments(node, smoothness=0.1): ''' Generator to convert a path node to an interator on segmented paths (bezier curves broken to approximated straights lines). ''' mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) d = node.get('d') if len(simplepath.parsePath(d)) == 0: return p = cubicsuperpath.parsePath(d) simpletransform.applyTransformToPath(mat, p) # p is now a list of lists of cubic beziers [ctrl p1, ctrl p2, endpoint] # where the start-point is the last point in the previous segment for sp in p: path = [] subdivideCubicPath(sp, smoothness) for csp in sp: path.append([csp[1][0], csp[1][1]]) yield path
def effect(self): if len(self.options.ids) < 2: inkex.errormsg(_("This extension requires two selected paths. \nThe second path must be exactly four nodes long.")) exit() #obj is selected second scale = self.unittouu('1px') # convert to document units obj = self.selected[self.options.ids[0]] trafo = self.selected[self.options.ids[1]] if obj.get(inkex.addNS('type','sodipodi')): inkex.errormsg(_("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type','sodipodi')))) exit() if obj.tag == inkex.addNS('path','svg') or obj.tag == inkex.addNS('g','svg'): if trafo.tag == inkex.addNS('path','svg'): #distil trafo into four node points mat = simpletransform.composeParents(trafo, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) trafo = cubicsuperpath.parsePath(trafo.get('d')) if len(trafo[0]) < 4: inkex.errormsg(_("This extension requires that the second selected path be four nodes long.")) exit() simpletransform.applyTransformToPath(mat, trafo) trafo = [[Point(csp[1][0],csp[1][1]) for csp in subs] for subs in trafo][0][:4] #vectors pointing away from the trafo origin self.t1 = Segment(trafo[0],trafo[1]) self.t2 = Segment(trafo[1],trafo[2]) self.t3 = Segment(trafo[3],trafo[2]) self.t4 = Segment(trafo[0],trafo[3]) #query inkscape about the bounding box of obj self.q = {'x':0,'y':0,'width':0,'height':0} file = self.args[-1] id = self.options.ids[0] for query in self.q.keys(): if bsubprocess: p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() self.q[query] = scale*float(p.stdout.read()) err = p.stderr.read() else: f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:] self.q[query] = scale*float(f.read()) f.close() err.close() if obj.tag == inkex.addNS("path",'svg'): self.process_path(obj) if obj.tag == inkex.addNS("g",'svg'): self.process_group(obj) else: if trafo.tag == inkex.addNS('g','svg'): inkex.errormsg(_("The second selected object is a group, not a path.\nTry using the procedure Object->Ungroup.")) else: inkex.errormsg(_("The second selected object is not a path.\nTry using the procedure Path->Object to Path.")) exit() else: inkex.errormsg(_("The first selected object is not a path.\nTry using the procedure Path->Object to Path.")) exit()
def effect(self): # if self.options.mformat == '"presets"': # self.setPreset() # njj: hack some options # get number of digits # prec = int(self.options.precision) prec = 2 self.options.fontsize = 20 self.options.unit = 'mm' self.options.scale = 1 self.options.angle = 0 self.options.offset = -6 scale = self.unittouu('1px') # convert to document units # self.options.offset *= scale factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): (viewx, viewy, vieww, viewh) = re.sub(' +|, +|,', ' ', doc.get('viewBox')).strip().split(' ', 4) factor = self.unittouu(doc.get('width')) / float(vieww) if self.unittouu(doc.get('height')) / float(viewh) < factor: factor = self.unittouu(doc.get('height')) / float(viewh) factor /= self.unittouu('1px') self.options.fontsize /= factor factor *= scale / self.unittouu('1' + self.options.unit) # Gather paths debug(dir(self)) paths = self.document.findall('.//{0}'.format(nspath)) # Act on paths for node in paths: mat = simpletransform.composeParents( node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) stotal = abs(measure.csparea(p) * factor * self.options.scale) self.group = inkex.etree.SubElement(node.getparent(), inkex.addNS('text', 'svg')) # Format the area as string resultstr = locale.format( "%(len)25." + str(prec) + "f", { 'len': round(stotal * factor * self.options.scale, prec) }).strip() # Fixed text, in the center of each path bbox = simpletransform.computeBBox([node]) tx = bbox[0] + (bbox[1] - bbox[0]) / 2.0 ty = bbox[2] + (bbox[3] - bbox[2]) / 2.0 anchor = 'middle' self.addTextWithTspan( self.group, tx, ty, resultstr + ' ' + self.options.unit + '^2', id, anchor, -int(self.options.angle), -self.options.offset + self.options.fontsize / 2)
def process_path(self, ipath, mat_x, mat_y, term1): mat = simpletransform.composeParents( ipath, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) path_string = ipath.get('d') svg_path = simplepath.parsePath(path_string) paths = [] # for path in svg_path: # inkex.debug("svg_path: " + str(svg_path)) for path in svg_path: if path[0] == 'M' or path[0] == 'L': paths.append([path[0], [path[1]]]) elif path[0] == 'C' or path[0] == 'Q': pts = [] if path[0] == 'C': num = 3 else: num = 2 for i in range(0, num): pt = [path[1][2 * i], path[1][2 * i + 1]] pts.append(pt) paths.append([path[0], pts]) elif path[0] == 'Z': paths.append(['Z', []]) # inkex.debug("paths: " + str(paths) + "\n\n") mat = simpletransform.invertTransform(mat) # simpletransform.applyTransformToPath(mat, p) for path in paths: for pt in path[1]: simpletransform.applyTransformToPoint(mat, pt) # do transformation for path in paths: for pt in path[1]: self.project_point(pt, mat_x, mat_y, term1) # back to original form res_paths = [] for path in paths: if path[0] == 'C' or path[0] == 'Q': flat_pts = [] for pt in path[1]: flat_pts.append(pt[0]) flat_pts.append(pt[1]) res_paths.append([path[0], flat_pts]) elif path[0] == 'M' or path[0] == 'L': res_paths.append([path[0], path[1][0]]) elif path[0] == 'Z': res_paths.append(path) # inkex.debug("res_paths: " + str(res_paths)) res_svg_paths = simplepath.formatPath(res_paths) # inkex.debug("res_svg_paths: " + str(res_svg_paths)) ipath.set('d', res_svg_paths)
def get_node_transform(node): # start with the identity transform transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] # combine this node's transform with all parent groups' transforms transform = simpletransform.composeParents(node, transform) # add in the transform implied by the viewBox viewbox_transform = get_viewbox_transform(node.getroottree().getroot()) transform = simpletransform.composeTransform(viewbox_transform, transform) return transform
def process_path(self,path): mat = simpletransform.composeParents(path, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) d = path.get('d') p = cubicsuperpath.parsePath(d) simpletransform.applyTransformToPath(mat, p) for subs in p: for csp in subs: csp[0] = self.trafopoint(csp[0]) csp[1] = self.trafopoint(csp[1]) csp[2] = self.trafopoint(csp[2]) mat = simpletransform.invertTransform(mat) simpletransform.applyTransformToPath(mat, p) path.set('d',cubicsuperpath.formatPath(p))
def get_node_transform(node): # start with the identity transform transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] # this if is because sometimes inkscape likes to create paths outside of a layer?! if node.getparent() is not None: # combine this node's transform with all parent groups' transforms transform = simpletransform.composeParents(node, transform) # add in the transform implied by the viewBox viewbox_transform = get_viewbox_transform(node.getroottree().getroot()) transform = simpletransform.composeTransform(viewbox_transform, transform) return transform
def apply_transforms(path, node): # start with the identity transform transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] # combine this node's transform with all parent groups' transforms transform = simpletransform.composeParents(node, transform) # add in the transform implied by the viewBox viewbox_transform = get_viewbox_transform(node.getroottree().getroot()) transform = simpletransform.composeTransform(viewbox_transform, transform) # apply the combined transform to this node's path simpletransform.applyTransformToPath(transform, path) return path
def parse_path(self): # A CSP is a "cubic superpath". # # A "path" is a sequence of strung-together bezier curves. # # A "superpath" is a collection of paths that are all in one object. # # The "cubic" bit in "cubic superpath" is because the bezier curves # inkscape uses involve cubic polynomials. # # Each path is a collection of tuples, each of the form: # # (control_before, point, control_after) # # A bezier curve segment is defined by an endpoint, a control point, # a second control point, and a final endpoint. A path is a bunch of # bezier curves strung together. One could represent a path as a set # of four-tuples, but there would be redundancy because the ending # point of one bezier is the starting point of the next. Instead, a # path is a set of 3-tuples as shown above, and one must construct # each bezier curve by taking the appropriate endpoints and control # points. Bleh. It should be noted that a straight segment is # represented by having the control point on each end equal to that # end's point. # # In a path, each element in the 3-tuple is itself a tuple of (x, y). # Tuples all the way down. Hasn't anyone heard of using classes? path = self.path # start with the identity transform transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] # combine this node's transform with all parent groups' transforms transform = simpletransform.composeParents(self.node, transform) # add in the transform implied by the viewBox viewbox_transform = get_viewbox_transform( self.node.getroottree().getroot()) transform = simpletransform.composeTransform(viewbox_transform, transform) # apply the combined transform to this node's path simpletransform.applyTransformToPath(transform, path) return path
def effect(self): """ Effect behaviour. """ # Get script's "--what" option value. fontsize = str(self.options.fontsize) + 'px' color = self.options.color font = self.options.font fontweight = self.options.fontweight replaced = self.options.replaced replacewith = self.options.replacewith angle = -int(self.options.angle) capitals = self.options.capitals if len(self.selected) == 0: inkex.errormsg(_("Please select some paths first.")) exit() for id, node in self.selected.iteritems(): mat = simpletransform.composeParents( node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) self.group = inkex.etree.SubElement(node.getparent(), inkex.addNS('text', 'svg')) tx, ty = cspcofm(p) new = inkex.etree.SubElement( self.group, inkex.addNS('tspan', 'svg'), {inkex.addNS('role', 'sodipodi'): 'line'}) s = { 'text-align': 'center', 'vertical-align': 'bottom', 'text-anchor': 'middle', 'font-size': fontsize, 'font-weight': fontweight, 'font-style': 'normal', 'font-family': font, 'fill': color } new.set('style', simplestyle.formatStyle(s)) if capitals: id = id.upper() new.text = id.replace(replaced, replacewith) self.group.set('x', str(tx)) self.group.set('y', str(ty)) self.group.set('transform', 'rotate(%s, %s, %s)' % (angle, tx, ty))
def effect(self): # get number of digits prec = int(self.options.precision) scale = self.unittouu('1px') # convert to document units self.options.offset *= scale factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = self.unittouu(doc.get('width'))/float(vieww) if self.unittouu(doc.get('height'))/float(viewh) < factor: factor = self.unittouu(doc.get('height'))/float(viewh) factor /= self.unittouu('1px') self.options.fontsize /= factor # loop over all selected paths for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg')) elif self.options.type == "area": stotal = csparea(p)*factor*self.options.scale self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg')) else: xc, yc = cspcofm(p) self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('path','svg')) self.group.set('id', 'MassCenter_' + node.get('id')) self.addCross(self.group, xc, yc, scale) continue # Format the length as string lenstr = locale.format("%(len)25."+str(prec)+"f",{'len':round(stotal*factor*self.options.scale,prec)}).strip() if self.options.format == 'textonpath': if self.options.type == "length": self.addTextOnPath(self.group, 0, 0, lenstr+' '+self.options.unit, id, 'start', '50%', self.options.offset) else: self.addTextOnPath(self.group, 0, 0, lenstr+' '+self.options.unit+'^2', id, 'start', '0%', self.options.offset) else: if self.options.type == "length": self.addTextWithTspan(self.group, p[0][0][1][0], p[0][0][1][1], lenstr+' '+self.options.unit, id, 'start', -int(self.options.angle), self.options.offset + self.options.fontsize/2) else: self.addTextWithTspan(self.group, p[0][0][1][0], p[0][0][1][1], lenstr+' '+self.options.unit+'^2', id, 'start', -int(self.options.angle), -self.options.offset + self.options.fontsize/2)
def effect(self): zoom = self.unittouu( str(self.options.zoom) + 'px') if self.options.randomize: imagelist = generate_random_string(self.options.text, zoom) else: tokens = tokenize(self.options.text) imagelist = randomize_input_string(tokens, zoom) image = layoutstring( imagelist, zoom ) if image: s = { 'stroke': 'none', 'fill': '#000000' } new = inkex.etree.Element(inkex.addNS('path','svg')) new.set('style', simplestyle.formatStyle(s)) new.set('d', simplepath.formatPath(image)) self.current_layer.append(new) # compensate preserved transforms of parent layer if self.current_layer.getparent() is not None: mat = simpletransform.composeParents(self.current_layer, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) simpletransform.applyTransformToNode(simpletransform.invertTransform(mat), new)
def effect(self): # get number of digits prec = int(self.options.precision) factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = float(doc.get('width'))/float(vieww) if float(doc.get('height'))/float(viewh) < factor: factor = float(doc.get('height'))/float(viewh) self.options.fontsize /= factor # loop over all selected paths for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg')) a =[] mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) factor = factor/inkex.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) else: stotal = csparea(p)*factor*self.options.scale # Format the length as string lenstr = locale.format("%(len)25."+str(prec)+"f",{'len':round(stotal*factor*self.options.scale,prec)}).strip() if self.options.format == 'textonpath': if self.options.type == "length": self.addTextOnPath(self.group, 0, 0, lenstr+' '+self.options.unit, id, 'start', '50%', self.options.offset) else: self.addTextOnPath(self.group, 0, 0, lenstr+' '+self.options.unit+'^2', id, 'start', '0%', self.options.offset) else: if self.options.type == "length": self.addTextWithTspan(self.group, p[0][0][1][0], p[0][0][1][1], lenstr+' '+self.options.unit, id, 'start', -int(self.options.angle), self.options.offset + self.options.fontsize/2) else: self.addTextWithTspan(self.group, p[0][0][1][0], p[0][0][1][1], lenstr+' '+self.options.unit+'^2', id, 'start', -int(self.options.angle), -self.options.offset + self.options.fontsize/2)
def effect(self): if len(self.options.ids) < 2: inkex.errormsg(_("This extension requires two selected paths.")) exit() #obj is selected second obj = self.selected[self.options.ids[0]] envelope = self.selected[self.options.ids[1]] if obj.get(inkex.addNS('type','sodipodi')): inkex.errormsg(_("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type','sodipodi')))) exit() if obj.tag == inkex.addNS('path','svg') or obj.tag == inkex.addNS('g','svg'): if envelope.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(envelope, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) path = cubicsuperpath.parsePath(envelope.get('d')) if len(path) < 1 or len(path[0]) < 4: inkex.errormsg(_("This extension requires that the second selected path be four nodes long.")) exit() simpletransform.applyTransformToPath(mat, path) dp = zeros((4,2), dtype=float64) for i in range(4): dp[i][0] = path[0][i][1][0] dp[i][1] = path[0][i][1][1] #query inkscape about the bounding box of obj q = {'x':0,'y':0,'width':0,'height':0} file = self.args[-1] id = self.options.ids[0] for query in q.keys(): if bsubprocess: p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = float(p.stdout.read()) err = p.stderr.read() else: f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:] q[query] = float(f.read()) f.close() err.close() sp = array([[q['x'], q['y']+q['height']],[q['x'], q['y']],[q['x']+q['width'], q['y']],[q['x']+q['width'], q['y']+q['height']]], dtype=float64) else: if envelope.tag == inkex.addNS('g','svg'): inkex.errormsg(_("The second selected object is a group, not a path.\nTry using the procedure Object->Ungroup.")) else: inkex.errormsg(_("The second selected object is not a path.\nTry using the procedure Path->Object to Path.")) exit() else: inkex.errormsg(_("The first selected object is not a path.\nTry using the procedure Path->Object to Path.")) exit() solmatrix = zeros((8,8), dtype=float64) free_term = zeros((8), dtype=float64) for i in (0,1,2,3): solmatrix[i][0] = sp[i][0] solmatrix[i][1] = sp[i][1] solmatrix[i][2] = 1 solmatrix[i][6] = -dp[i][0]*sp[i][0] solmatrix[i][7] = -dp[i][0]*sp[i][1] solmatrix[i+4][3] = sp[i][0] solmatrix[i+4][4] = sp[i][1] solmatrix[i+4][5] = 1 solmatrix[i+4][6] = -dp[i][1]*sp[i][0] solmatrix[i+4][7] = -dp[i][1]*sp[i][1] free_term[i] = dp[i][0] free_term[i+4] = dp[i][1] res = solve(solmatrix, free_term) projmatrix = array([[res[0],res[1],res[2]],[res[3],res[4],res[5]],[res[6],res[7],1.0]],dtype=float64) if obj.tag == inkex.addNS("path",'svg'): self.process_path(obj,projmatrix) if obj.tag == inkex.addNS("g",'svg'): self.process_group(obj,projmatrix)
def effect(self): docW = self.unittouu(self.document.getroot().get('width')) docH = self.unittouu(self.document.getroot().get('height')) boxW = self.unittouu(str(self.options.width) + self.options.unit) boxH = self.unittouu(str(self.options.height) + self.options.unit) boxD = self.unittouu(str(self.options.depth) + self.options.unit) tabProp = self.options.tabProportion tabH = boxD * tabProp box_id = self.uniqueId('box') self.box = g = inkex.etree.SubElement(self.current_layer, 'g', {'id': box_id}) line_style = simplestyle.formatStyle({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) }) #self.createGuide( 0, docH, 0 ); # Inner Close Tab line_path = [['M', [boxW - (tabH * 0.7), 0]], [ 'C', [ boxW - (tabH * 0.25), 0, boxW, tabH * 0.3, boxW, tabH * 0.9 ] ], ['L', [boxW, tabH]], ['L', [0, tabH]], ['L', [0, tabH * 0.9]], ['C', [0, tabH * 0.3, tabH * 0.25, 0, tabH * 0.7, 0]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-inner-close-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) lower_pos = boxD + tabH left_pos = 0 #self.createGuide( 0, docH-tabH, 0 ); # Upper Close Tab line_path = [['M', [left_pos, tabH]], ['L', [left_pos + boxW, tabH]], ['L', [left_pos + boxW, lower_pos]], ['L', [left_pos + 0, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-upper-close-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxW # Upper Right Tab sideTabH = lower_pos - (boxW / 2) if sideTabH < tabH: sideTabH = tabH line_path = [['M', [left_pos, sideTabH]], ['L', [left_pos + (boxD * 0.8), sideTabH]], [ 'L', [left_pos + boxD, ((lower_pos * 3) - sideTabH) / 3] ], ['L', [left_pos + boxD, lower_pos]], ['L', [left_pos + 0, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-upper-right-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxW + boxD # Upper Left Tab line_path = [['M', [left_pos + boxD, sideTabH]], ['L', [left_pos + (boxD * 0.2), sideTabH]], ['L', [left_pos, ((lower_pos * 3) - sideTabH) / 3]], ['L', [left_pos, lower_pos]], ['L', [left_pos + boxD, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-upper-left-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos = 0 #self.createGuide( 0, docH-tabH-boxD, 0 ); # Right Tab line_path = [ ['M', [left_pos, lower_pos]], ['L', [left_pos - (boxD / 2), lower_pos + (boxD / 4)]], ['L', [left_pos - (boxD / 2), lower_pos + boxH - (boxD / 4)]], ['L', [left_pos, lower_pos + boxH]], ['Z', []] ] line_atts = { 'style': line_style, 'id': box_id + '-left-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) # Front line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos + boxW, lower_pos]], ['L', [left_pos + boxW, lower_pos + boxH]], ['L', [left_pos, lower_pos + boxH]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-front', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxW # Right line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos + boxD, lower_pos]], ['L', [left_pos + boxD, lower_pos + boxH]], ['L', [left_pos, lower_pos + boxH]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-right', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxD # Back line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos + boxW, lower_pos]], ['L', [left_pos + boxW, lower_pos + boxH]], ['L', [left_pos, lower_pos + boxH]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-back', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxW # Left line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos + boxD, lower_pos]], ['L', [left_pos + boxD, lower_pos + boxH]], ['L', [left_pos, lower_pos + boxH]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-left', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) lower_pos += boxH left_pos = 0 bTab = lower_pos + boxD if bTab > boxW / 2.5: bTab = boxW / 2.5 # Bottom Front Tab line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos, lower_pos + (boxD / 2)]], ['L', [left_pos + boxW, lower_pos + (boxD / 2)]], ['L', [left_pos + boxW, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-bottom-front-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxW # Bottom Right Tab line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos, lower_pos + bTab]], ['L', [left_pos + boxD, lower_pos + bTab]], ['L', [left_pos + boxD, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-bottom-right-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxD # Bottom Back Tab line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos, lower_pos + (boxD / 2)]], ['L', [left_pos + boxW, lower_pos + (boxD / 2)]], ['L', [left_pos + boxW, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-bottom-back-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxW # Bottom Left Tab line_path = [['M', [left_pos, lower_pos]], ['L', [left_pos, lower_pos + bTab]], ['L', [left_pos + boxD, lower_pos + bTab]], ['L', [left_pos + boxD, lower_pos]], ['Z', []]] line_atts = { 'style': line_style, 'id': box_id + '-bottom-left-tab', 'd': formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path', 'svg'), line_atts) left_pos += boxD lower_pos += bTab g.set( 'transform', 'translate(%f,%f)' % ((docW - left_pos) / 2, (docH - lower_pos) / 2)) # compensate preserved transforms of parent layer if self.current_layer.getparent() is not None: mat = simpletransform.composeParents( self.current_layer, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) simpletransform.applyTransformToNode( simpletransform.invertTransform(mat), g)
def effect(self): if len(self.options.ids) < 2: inkex.errormsg(_("This extension requires two selected paths.")) exit() #obj is selected second scale = self.unittouu('1px') # convert to document units obj = self.selected[self.options.ids[0]] envelope = self.selected[self.options.ids[1]] if obj.get(inkex.addNS('type', 'sodipodi')): inkex.errormsg( _("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type', 'sodipodi')))) exit() if obj.tag == inkex.addNS('path', 'svg') or obj.tag == inkex.addNS( 'g', 'svg'): if envelope.tag == inkex.addNS('path', 'svg'): mat = simpletransform.composeParents( envelope, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) path = cubicsuperpath.parsePath(envelope.get('d')) if len(path) < 1 or len(path[0]) < 4: inkex.errormsg( _("This extension requires that the second selected path be four nodes long." )) exit() simpletransform.applyTransformToPath(mat, path) dp = zeros((4, 2), dtype=float64) for i in range(4): dp[i][0] = path[0][i][1][0] dp[i][1] = path[0][i][1][1] #query inkscape about the bounding box of obj q = {'x': 0, 'y': 0, 'width': 0, 'height': 0} file = self.args[-1] id = self.options.ids[0] for query in q.keys(): if bsubprocess: p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query, id, file), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = scale * float(p.stdout.read()) err = p.stderr.read() else: f, err = os.popen3( 'inkscape --query-%s --query-id=%s "%s"' % (query, id, file))[1:] q[query] = scale * float(f.read()) f.close() err.close() sp = array([[q['x'], q['y'] + q['height']], [q['x'], q['y']], [q['x'] + q['width'], q['y']], [q['x'] + q['width'], q['y'] + q['height']]], dtype=float64) else: if envelope.tag == inkex.addNS('g', 'svg'): inkex.errormsg( _("The second selected object is a group, not a path.\nTry using the procedure Object->Ungroup." )) else: inkex.errormsg( _("The second selected object is not a path.\nTry using the procedure Path->Object to Path." )) exit() else: inkex.errormsg( _("The first selected object is not a path.\nTry using the procedure Path->Object to Path." )) exit() solmatrix = zeros((8, 8), dtype=float64) free_term = zeros((8), dtype=float64) for i in (0, 1, 2, 3): solmatrix[i][0] = sp[i][0] solmatrix[i][1] = sp[i][1] solmatrix[i][2] = 1 solmatrix[i][6] = -dp[i][0] * sp[i][0] solmatrix[i][7] = -dp[i][0] * sp[i][1] solmatrix[i + 4][3] = sp[i][0] solmatrix[i + 4][4] = sp[i][1] solmatrix[i + 4][5] = 1 solmatrix[i + 4][6] = -dp[i][1] * sp[i][0] solmatrix[i + 4][7] = -dp[i][1] * sp[i][1] free_term[i] = dp[i][0] free_term[i + 4] = dp[i][1] res = solve(solmatrix, free_term) projmatrix = array([[res[0], res[1], res[2]], [res[3], res[4], res[5]], [res[6], res[7], 1.0]], dtype=float64) if obj.tag == inkex.addNS("path", 'svg'): self.process_path(obj, projmatrix) if obj.tag == inkex.addNS("g", 'svg'): self.process_group(obj, projmatrix)
def effect(self): if self.options.mformat == '"presets"': self.setPreset() # get number of digits prec = int(self.options.precision) scale = self.unittouu('1px') # convert to document units self.options.offset *= scale factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = self.unittouu(doc.get('width')) / float(vieww) if self.unittouu(doc.get('height')) / float(viewh) < factor: factor = self.unittouu(doc.get('height')) / float(viewh) factor /= self.unittouu('1px') self.options.fontsize /= factor factor *= scale / self.unittouu('1' + self.options.unit) # loop over all selected paths for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path', 'svg'): mat = simpletransform.composeParents( node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) if self.options.mtype == "length": slengths, stotal = csplength(p) self.group = inkex.etree.SubElement( node.getparent(), inkex.addNS('text', 'svg')) elif self.options.mtype == "area": stotal = abs(csparea(p) * factor * self.options.scale) self.group = inkex.etree.SubElement( node.getparent(), inkex.addNS('text', 'svg')) else: xc, yc = cspcofm(p) self.group = inkex.etree.SubElement( node.getparent(), inkex.addNS('path', 'svg')) self.group.set('id', 'MassCenter_' + node.get('id')) self.addCross(self.group, xc, yc, scale) continue # Format the length as string lenstr = locale.format("%(len)25." + str(prec) + "f", { 'len': round(stotal * factor * self.options.scale, prec) }).strip() if self.options.mformat == '"textonpath"': startOffset = self.options.startOffset if startOffset == "custom": startOffset = str(self.options.startOffsetCustom) + '%' if self.options.mtype == "length": self.addTextOnPath(self.group, 0, 0, lenstr + ' ' + self.options.unit, id, self.options.anchor, startOffset, self.options.offset) else: self.addTextOnPath( self.group, 0, 0, lenstr + ' ' + self.options.unit + '^2', id, self.options.anchor, startOffset, self.options.offset) elif self.options.mformat == '"fixedtext"': if self.options.position == "mass": tx, ty = cspcofm(p) anchor = 'middle' elif self.options.position == "center": bbox = simpletransform.computeBBox([node]) tx = bbox[0] + (bbox[1] - bbox[0]) / 2.0 ty = bbox[2] + (bbox[3] - bbox[2]) / 2.0 anchor = 'middle' else: # default tx = p[0][0][1][0] ty = p[0][0][1][1] anchor = 'start' if self.options.mtype == "length": self.addTextWithTspan( self.group, tx, ty, lenstr + ' ' + self.options.unit, id, anchor, -int(self.options.angle), self.options.offset + self.options.fontsize / 2) else: self.addTextWithTspan( self.group, tx, ty, lenstr + ' ' + self.options.unit + '^2', id, anchor, -int(self.options.angle), -self.options.offset + self.options.fontsize / 2) else: # center of mass, no text pass
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 getTotalTransform(node): ''' Shorthand method that is lacking in simpletransform ''' if node.tag == inkex.addNS("svg", "svg"): return SpeleoTransform.Identity return simpletransform.composeParents(node, SpeleoTransform.Identity)
def generatePoints(obj, offset, n): # Create n equidistant points around the path pointList = [] targetDist = offset * read_stored_info("pathlength", obj)/ n segmentLengths = [0.0] + read_stored_info("segmentlengths", obj)[::-1] mat = simpletransform.composeParents(obj, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(obj.get('d')) simpletransform.applyTransformToPath(mat, p) segments = p[0] new_path = segments i = 0 count = 0 total = 0 while i < len(segments): # Cycle through path and add a node where targetDist = 0 if segmentLengths[i] == targetDist: pointList += [segments[i][1]] targetDist = read_stored_info("pathlength", obj)/ n elif targetDist > segmentLengths[i] or segmentLengths[i] == 0: targetDist -= segmentLengths[i] else: t = targetDist / float(segmentLengths[i]) t1 = segments[i-1][1] t2 = segments[i][1] pathList = addnodes.cspbezsplitatlength(segments[i-1], segments[i], t,tolerance=0.00001) pointList += [pathList[1][1]] prev = segments[:i - 1] next = segments[i + 1:] segments = prev + pathList + next len1 = targetDist len2 = segmentLengths[i] - targetDist if abs((len1 + len2) - segmentLengths[i]) >= 0.0001: raise Exception("There is an issue with the bezier split function. (" + str(len1 + len2) + " vs. " + str(segmentLengths[i]) + ")") prev = segmentLengths[:i] next = segmentLengths[i+1:] segmentLengths = prev + [len1, len2] + next targetDist = read_stored_info("pathlength", obj)/n count += 1 if(len(pointList) == n): break; i += 1 pointList += [segments[0][1]] if abs(sum(segmentLengths) - read_stored_info("pathlength", obj)) >= 0.001: raise Exception("Internal Error: The total length of the new path does not equal the original path.") obj.set('d', cubicsuperpath.formatPath([segments[:-1]])+'Z') obj.set('segmentlengths', str(segmentLengths)) return pointList
def effect(self): # get number of digits prec = int(self.options.precision) scale = self.unittouu("1px") # convert to document units self.options.offset *= scale factor = 1.0 doc = self.document.getroot() if doc.get("viewBox"): [viewx, viewy, vieww, viewh] = doc.get("viewBox").split(" ") factor = self.unittouu(doc.get("width")) / float(vieww) if self.unittouu(doc.get("height")) / float(viewh) < factor: factor = self.unittouu(doc.get("height")) / float(viewh) factor /= self.unittouu("1px") self.options.fontsize /= factor factor *= scale / self.unittouu("1" + self.options.unit) # loop over all selected paths for id, node in self.selected.iteritems(): if node.tag == inkex.addNS("path", "svg"): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get("d")) simpletransform.applyTransformToPath(mat, p) if self.options.type == "length": slengths, stotal = csplength(p) self.group = inkex.etree.SubElement(node.getparent(), inkex.addNS("text", "svg")) elif self.options.type == "area": stotal = csparea(p) * factor * self.options.scale self.group = inkex.etree.SubElement(node.getparent(), inkex.addNS("text", "svg")) else: xc, yc = cspcofm(p) self.group = inkex.etree.SubElement(node.getparent(), inkex.addNS("path", "svg")) self.group.set("id", "MassCenter_" + node.get("id")) self.addCross(self.group, xc, yc, scale) continue # Format the length as string lenstr = locale.format( "%(len)25." + str(prec) + "f", {"len": round(stotal * factor * self.options.scale, prec)} ).strip() if self.options.format == "textonpath": if self.options.type == "length": self.addTextOnPath( self.group, 0, 0, lenstr + " " + self.options.unit, id, "start", "50%", self.options.offset ) else: self.addTextOnPath( self.group, 0, 0, lenstr + " " + self.options.unit + "^2", id, "start", "0%", self.options.offset, ) else: if self.options.type == "length": self.addTextWithTspan( self.group, p[0][0][1][0], p[0][0][1][1], lenstr + " " + self.options.unit, id, "start", -int(self.options.angle), self.options.offset + self.options.fontsize / 2, ) else: self.addTextWithTspan( self.group, p[0][0][1][0], p[0][0][1][1], lenstr + " " + self.options.unit + "^2", id, "start", -int(self.options.angle), -self.options.offset + self.options.fontsize / 2, )
def effect(self): # Get number of digits scale = self.unittouu('1px') # Convert to document units factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = self.unittouu(doc.get('width'))/float(vieww) if self.unittouu(doc.get('height'))/float(viewh) < factor: factor = self.unittouu(doc.get('height'))/float(viewh) factor /= self.unittouu('1px') # Loop over all selected paths obj_lengths = [] obj_ids = [] obj_nodes = [] for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) node.set('d', cubicsuperpath.formatPath(p)) simpletransform.applyTransformToPath(mat, p) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) # Save the path length and segment lengths in the document node.set('pathlength', str(stotal)) tmp = '' for slen in slengths[0][::-1]: tmp += str(slen) + ' ' tmp = tmp[:-1] # Remove the space at the end node.set('segmentlengths', tmp) obj_lengths += [stotal] obj_ids += [id] obj_nodes += [node] id_min = 0 id_max = 1 minOrigin = [] maxOrigin = [] # Set bigger and smaller object if obj_lengths[id_min] > obj_lengths[id_max]: id_min = 1 id_max = 0 minOrigin = originParse(obj_nodes[id_min]) maxOrigin = originParse(obj_nodes[id_max]) #Scaling Radio Button Options if self.options.radioScale == "B2S": ratio = obj_lengths[id_min] / obj_lengths[id_max] obj_ori = [] ori_trans = [] obj_nodes[id_max].set('transform', 'scale(' + str(ratio) + ' ' + str(ratio) +')') fuseTransform(obj_nodes[id_max]) obj_ori = originParse(obj_nodes[id_max]) ori_trans = [(maxOrigin[0] - obj_ori[0]), (maxOrigin[1] - obj_ori[1])] obj_nodes[id_max].set('transform', 'translate(' + str(ori_trans[0]) + ' ' + str(ori_trans[1]) +')') fuseTransform(obj_nodes[id_max]) elif self.options.radioScale == "S2B": ratio = obj_lengths[id_max] / obj_lengths[id_min] obj_ori = [] ori_trans = [] obj_nodes[id_min].set('transform', 'scale(' + str(ratio) + ' ' + str(ratio) +')') fuseTransform(obj_nodes[id_min]) obj_ori = originParse(obj_nodes[id_min]) ori_trans = [(minOrigin[0] - obj_ori[0]), (minOrigin[1] - obj_ori[1])] obj_nodes[id_min].set('transform', 'translate(' + str(ori_trans[0]) + ' ' + str(ori_trans[1]) +')') fuseTransform(obj_nodes[id_min]) # Get paths and collect pathlength and segmentlengths obj_lengths = [] obj_ids = [] obj_nodes = [] for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) node.set('d', cubicsuperpath.formatPath(p)) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) # Save the path length and segment lengths in the document node.set('pathlength', str(stotal)) tmp = '' for slen in slengths[0][::-1]: tmp += str(slen) + ' ' tmp = tmp[:-1] #Remove the space at the end node.set('segmentlengths', tmp) obj_lengths += [stotal] obj_ids += [id] obj_nodes += [node] # Format the length as string points = [] # Run Functions based on active Tab if self.options.tab == "\"stitch\"": addStitching(obj_nodes[id_min], self.options.points, self.options.offset, self.options.paraStitch, doc) addStitching(obj_nodes[id_max], self.options.points, self.options.offset, self.options.paraStitch, doc) elif self.options.tab == "\"tooth\"": addNotches(obj_nodes[id_min], self.options.points, self.options.offset, False, self.options.paraTooth,doc) addNotches(obj_nodes[id_max], self.options.points, self.options.offset, True, self.options.paraTooth,doc) elif self.options.tab == "\"leaf\"": addLeaves(obj_nodes[id_min], self.options.points, self.options.offset, self.options.paraLeaf, doc) addLeaves(obj_nodes[id_max], self.options.points, self.options.offset, self.options.paraLeaf, doc)
def effect(self): # Get number of digits scale = self.unittouu('1px') # Convert to document units factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = self.unittouu(doc.get('width'))/float(vieww) if self.unittouu(doc.get('height'))/float(viewh) < factor: factor = self.unittouu(doc.get('height'))/float(viewh) factor /= self.unittouu('1px') # Loop over all selected paths obj_lengths = [] obj_ids = [] obj_nodes = [] for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) node.set('d', cubicsuperpath.formatPath(p)) simpletransform.applyTransformToPath(mat, p) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) # Save the path length and segment lengths in the document node.set('pathlength', str(stotal)) tmp = '' for slen in slengths[0][::-1]: tmp += str(slen) + ' ' tmp = tmp[:-1] # Remove the space at the end node.set('segmentlengths', tmp) obj_lengths += [stotal] obj_ids += [id] obj_nodes += [node] # Format the length as string id_min = 0 id_max = 1 # Set bigger and smaller object if obj_lengths[id_min] > obj_lengths[id_max]: id_min = 1 id_max = 0 # Get paths and collect pathlength and segmentlengths obj_lengths = [] obj_ids = [] obj_nodes = [] for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) node.set('d', cubicsuperpath.formatPath(p)) factor *= scale/self.unittouu('1'+self.options.unit) if self.options.type == "length": slengths, stotal = csplength(p) # Save the path length and segment lengths in the document node.set('pathlength', str(stotal)) tmp = '' for slen in slengths[0][::-1]: tmp += str(slen) + ' ' tmp = tmp[:-1] # Remove the space at the end node.set('segmentlengths', tmp) obj_lengths += [stotal] obj_ids += [id] obj_nodes += [node] # Format the length as string points = [] # Apply the leaves method to both paths addLeaves(obj_nodes[id_min], self.options.pointsL, self.options.offsetL, self.options.slideL, doc) addLeaves(obj_nodes[id_max], self.options.pointsL, self.options.offsetL, self.options.slideL, doc)
def effect(self): if len(self.options.ids) < 2: inkex.errormsg(_("This extension requires two selected paths.")) exit() #obj is selected second scale = self.unittouu('1px') # convert to document units obj = self.selected[self.options.ids[0]] envelope = self.selected[self.options.ids[1]] envelopes = [ self.selected[self.options.ids[i]] for i in range(1, len(self.options.ids)) ] # inkex.debug("envelopes: " + str(envelopes)) if obj.get(inkex.addNS('type', 'sodipodi')): inkex.errormsg( _("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type', 'sodipodi')))) exit() if obj.tag == inkex.addNS('path', 'svg') or obj.tag == inkex.addNS( 'g', 'svg'): #query inkscape about the bounding box of obj q = {'x': 0, 'y': 0, 'width': 0, 'height': 0} file = self.args[-1] id = self.options.ids[0] for query in q.keys(): if bsubprocess: p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query, id, file), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = scale * float(p.stdout.read()) err = p.stderr.read() else: f, err = os.popen3( 'inkscape --query-%s --query-id=%s "%s"' % (query, id, file))[1:] q[query] = scale * float(f.read()) f.close() err.close() sp = numpy.array([[q['x'], q['y'] + q['height']], [q['x'], q['y']], [q['x'] + q['width'], q['y']], [q['x'] + q['width'], q['y'] + q['height']]]) self.q = q # map each quad for envelope in envelopes: obj_copy = copy.deepcopy(obj) self.document.getroot().append(obj_copy) if envelope.tag == inkex.addNS('path', 'svg'): mat = simpletransform.composeParents( envelope, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) path = cubicsuperpath.parsePath(envelope.get('d')) if len(path) < 1 or len(path[0]) < 4: inkex.errormsg( _("This extension requires that the second selected path be four nodes long." )) exit() simpletransform.applyTransformToPath(mat, path) dp = numpy.zeros((4, 2)) for i in range(4): dp[i][0] = path[0][i][1][0] dp[i][1] = path[0][i][1][1] mat_y = numpy.array([[dp[0][1], dp[1][1]], [dp[3][1], dp[2][1]]]) mat_x = numpy.array([[dp[0][0], dp[1][0]], [dp[3][0], dp[2][0]]]) term1 = 1.0 / (q['width'] * q['height']) if obj.tag == inkex.addNS("path", 'svg'): self.process_path(obj_copy, mat_x, mat_y, term1) if obj.tag == inkex.addNS("g", 'svg'): self.process_group(obj_copy, mat_x, mat_y, term1) else: if envelope.tag == inkex.addNS('g', 'svg'): inkex.errormsg( _("The second selected object is a group, not a path.\nTry using the procedure Object->Ungroup." )) else: inkex.errormsg( _("The second selected object is not a path.\nTry using the procedure Path->Object to Path." )) exit() else: inkex.errormsg( _("The first selected object is not a path.\nTry using the procedure Path->Object to Path." )) exit()
def effect(self): docW = self.unittouu(self.document.getroot().get('width')) docH = self.unittouu(self.document.getroot().get('height')) boxW = self.unittouu( str(self.options.width) + self.options.unit ) boxH = self.unittouu( str(self.options.height) + self.options.unit ) boxD = self.unittouu( str(self.options.depth) + self.options.unit ) tabProp = self.options.tabProportion tabH = boxD * tabProp box_id = self.uniqueId('box') self.box = g = inkex.etree.SubElement(self.current_layer, 'g', {'id':box_id}) line_style = simplestyle.formatStyle({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) }) #self.createGuide( 0, docH, 0 ); # Inner Close Tab line_path = [ [ 'M', [ boxW-(tabH*0.7), 0 ] ], [ 'C', [ boxW-(tabH*0.25), 0, boxW, tabH*0.3, boxW, tabH*0.9 ] ], [ 'L', [ boxW, tabH ] ], [ 'L', [ 0, tabH ] ], [ 'L', [ 0, tabH*0.9 ] ], [ 'C', [ 0, tabH*0.3, tabH*0.25, 0, tabH*0.7, 0 ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-inner-close-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) lower_pos = boxD+tabH left_pos = 0 #self.createGuide( 0, docH-tabH, 0 ); # Upper Close Tab line_path = [ [ 'M', [ left_pos, tabH ] ], [ 'L', [ left_pos + boxW, tabH ] ], [ 'L', [ left_pos + boxW, lower_pos ] ], [ 'L', [ left_pos + 0, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-upper-close-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxW # Upper Right Tab sideTabH = lower_pos - (boxW/2) if sideTabH < tabH: sideTabH = tabH line_path = [ [ 'M', [ left_pos, sideTabH ] ], [ 'L', [ left_pos + (boxD*0.8), sideTabH ] ], [ 'L', [ left_pos + boxD, ((lower_pos*3)-sideTabH)/3 ] ], [ 'L', [ left_pos + boxD, lower_pos ] ], [ 'L', [ left_pos + 0, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-upper-right-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxW + boxD # Upper Left Tab line_path = [ [ 'M', [ left_pos + boxD, sideTabH ] ], [ 'L', [ left_pos + (boxD*0.2), sideTabH ] ], [ 'L', [ left_pos, ((lower_pos*3)-sideTabH)/3 ] ], [ 'L', [ left_pos, lower_pos ] ], [ 'L', [ left_pos + boxD, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-upper-left-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos = 0 #self.createGuide( 0, docH-tabH-boxD, 0 ); # Right Tab line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos - (boxD/2), lower_pos + (boxD/4) ] ], [ 'L', [ left_pos - (boxD/2), lower_pos + boxH - (boxD/4) ] ], [ 'L', [ left_pos, lower_pos + boxH ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-left-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) # Front line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos + boxW, lower_pos ] ], [ 'L', [ left_pos + boxW, lower_pos + boxH ] ], [ 'L', [ left_pos, lower_pos + boxH ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-front', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxW # Right line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos + boxD, lower_pos ] ], [ 'L', [ left_pos + boxD, lower_pos + boxH ] ], [ 'L', [ left_pos, lower_pos + boxH ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-right', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxD # Back line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos + boxW, lower_pos ] ], [ 'L', [ left_pos + boxW, lower_pos + boxH ] ], [ 'L', [ left_pos, lower_pos + boxH ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-back', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxW # Left line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos + boxD, lower_pos ] ], [ 'L', [ left_pos + boxD, lower_pos + boxH ] ], [ 'L', [ left_pos, lower_pos + boxH ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-left', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) lower_pos += boxH left_pos = 0 bTab = lower_pos + boxD if bTab > boxW / 2.5: bTab = boxW / 2.5 # Bottom Front Tab line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos, lower_pos + (boxD/2) ] ], [ 'L', [ left_pos + boxW, lower_pos + (boxD/2) ] ], [ 'L', [ left_pos + boxW, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-bottom-front-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxW # Bottom Right Tab line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos, lower_pos + bTab ] ], [ 'L', [ left_pos + boxD, lower_pos + bTab ] ], [ 'L', [ left_pos + boxD, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-bottom-right-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxD # Bottom Back Tab line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos, lower_pos + (boxD/2) ] ], [ 'L', [ left_pos + boxW, lower_pos + (boxD/2) ] ], [ 'L', [ left_pos + boxW, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-bottom-back-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxW # Bottom Left Tab line_path = [ [ 'M', [ left_pos, lower_pos ] ], [ 'L', [ left_pos, lower_pos + bTab ] ], [ 'L', [ left_pos + boxD, lower_pos + bTab ] ], [ 'L', [ left_pos + boxD, lower_pos ] ], [ 'Z', [] ] ] line_atts = { 'style':line_style, 'id':box_id+'-bottom-left-tab', 'd':formatPath(line_path) } inkex.etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) left_pos += boxD lower_pos += bTab g.set( 'transform', 'translate(%f,%f)' % ( (docW-left_pos)/2, (docH-lower_pos)/2 ) ) # compensate preserved transforms of parent layer if self.current_layer.getparent() is not None: mat = simpletransform.composeParents(self.current_layer, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) simpletransform.applyTransformToNode(simpletransform.invertTransform(mat), g)
def effect(self): if self.options.mformat == '"presets"': self.setPreset() # get number of digits prec = int(self.options.precision) scale = self.unittouu('1px') # convert to document units self.options.offset *= scale factor = 1.0 doc = self.document.getroot() if doc.get('viewBox'): [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ') factor = self.unittouu(doc.get('width'))/float(vieww) if self.unittouu(doc.get('height'))/float(viewh) < factor: factor = self.unittouu(doc.get('height'))/float(viewh) factor /= self.unittouu('1px') self.options.fontsize /= factor factor *= scale/self.unittouu('1'+self.options.unit) # loop over all selected paths for id, node in self.selected.iteritems(): if node.tag == inkex.addNS('path','svg'): mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) p = cubicsuperpath.parsePath(node.get('d')) simpletransform.applyTransformToPath(mat, p) if self.options.mtype == "length": slengths, stotal = csplength(p) self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg')) elif self.options.mtype == "area": stotal = abs(csparea(p)*factor*self.options.scale) self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg')) else: xc, yc = cspcofm(p) self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('path','svg')) self.group.set('id', 'MassCenter_' + node.get('id')) self.addCross(self.group, xc, yc, scale) continue # Format the length as string lenstr = locale.format("%(len)25."+str(prec)+"f",{'len':round(stotal*factor*self.options.scale,prec)}).strip() if self.options.mformat == '"textonpath"': startOffset = self.options.startOffset if startOffset == "custom": startOffset = str(self.options.startOffsetCustom) + '%' if self.options.mtype == "length": self.addTextOnPath(self.group, 0, 0, lenstr+' '+self.options.unit, id, self.options.anchor, startOffset, self.options.offset) else: self.addTextOnPath(self.group, 0, 0, lenstr+' '+self.options.unit+'^2', id, self.options.anchor, startOffset, self.options.offset) elif self.options.mformat == '"fixedtext"': if self.options.position == "mass": tx, ty = cspcofm(p) anchor = 'middle' elif self.options.position == "center": bbox = simpletransform.computeBBox([node]) tx = bbox[0] + (bbox[1] - bbox[0])/2.0 ty = bbox[2] + (bbox[3] - bbox[2])/2.0 anchor = 'middle' else: # default tx = p[0][0][1][0] ty = p[0][0][1][1] anchor = 'start' if self.options.mtype == "length": self.addTextWithTspan(self.group, tx, ty, lenstr+' '+self.options.unit, id, anchor, -int(self.options.angle), self.options.offset + self.options.fontsize/2) else: self.addTextWithTspan(self.group, tx, ty, lenstr+' '+self.options.unit+'^2', id, anchor, -int(self.options.angle), -self.options.offset + self.options.fontsize/2) else: # center of mass, no text pass