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 to_patches(self, last_patch=None): patches = [] source_node = get_clone_source(self.node) if source_node.tag not in EMBROIDERABLE_TAGS: return [] clone = copy(source_node) # set id clone_id = 'clone__%s__%s' % (self.node.get('id', ''), clone.get('id', '')) clone.set('id', clone_id) # apply transform transform = get_node_transform(self.node) applyTransformToNode(transform, clone) # apply style stroke_style = self.get_clone_style('stroke', self.node) if not stroke_style: stroke_style = self.get_clone_style('stroke', source_node) fill_style = self.node.get('fill') if not fill_style: fill_style = self.get_clone_style('fill', source_node, "#000000") fill_opacity = self.node.get('fill-opacity') if not fill_opacity: fill_opacity = self.get_clone_style('fill-opacity', source_node, "1") style = "fill:%s;fill-opacity:%s;" % (fill_style, fill_opacity) if stroke_style: style += "stroke:%s;" % stroke_style clone.set('style', style) # set fill angle. Use either # a. a custom set fill angle # b. calculated rotation for the cloned fill element to look exactly as it's source param = INKSTITCH_ATTRIBS['angle'] if self.clone_fill_angle is not None: angle = self.clone_fill_angle else: # clone angle clone_mat = parseTransform(clone.get('transform', '')) clone_angle = degrees(atan(-clone_mat[1][0] / clone_mat[1][1])) # source node angle source_mat = parseTransform(source_node.get('transform', '')) source_angle = degrees(atan(-source_mat[1][0] / source_mat[1][1])) # source node fill angle source_fill_angle = source_node.get(param, 0) angle = clone_angle + float(source_fill_angle) - source_angle clone.set(param, str(angle)) elements = self.clone_to_element(clone) for element in elements: patches.extend(element.to_patches(last_patch)) return patches
def copy_pattern(self, x, y): p = copy.deepcopy(self.ptrn) cx = float(self.ptrn.get('cx')) cy = float(self.ptrn.get('cy')) transformation = 'translate(' + str(x - cx) + ', ' + str(y - cy) + ')' transform = simpletransform.parseTransform(transformation) simpletransform.applyTransformToNode(transform, p) self.current_layer.append(p)
def scaleRoot(self, svg): """Scale all top-level elements in SVG root.""" # update viewport widthNumber = self.parse_length(svg.get('width'))[0] heightNumber = self.convert_length(*self.parse_length(svg.get('height')))[0] widthDoc = widthNumber * self.factor_a * self.unitExponent heightDoc = heightNumber * self.factor_a * self.unitExponent if svg.get('height'): svg.set('height', str(heightDoc)) if svg.get('width'): svg.set('width', str(widthDoc)) # update viewBox if svg.get('viewBox'): viewboxstring = re.sub(' +|, +|,',' ', svg.get('viewBox')) viewboxlist = [float(i) for i in viewboxstring.strip().split(' ', 4)] svg.set('viewBox','{} {} {} {}'.format(*[(val * self.factor_a) for val in viewboxlist])) # update guides, grids if self.options.switcher == "1": # FIXME: dpi96to90 only? self.scaleGuides(svg) self.scaleGrid(svg) for element in svg: # iterate all top-level elements of SVGRoot # init variables tag = etree.QName(element).localname width_scale = self.factor_a height_scale = self.factor_a if tag in GRAPHICS_ELEMENTS or tag in CONTAINER_ELEMENTS: # test for specific elements to skip from scaling if is_3dbox(element): if check_3dbox(svg, element, width_scale, height_scale): continue if is_text_on_path(element): if check_text_on_path(svg, element, width_scale, height_scale): continue if is_use(element): if check_use(svg, element, width_scale, height_scale): continue # relative units ('%') in presentation attributes for attr in ['width', 'height']: self.scale_attr_val(element, attr, ['%'], 1.0 / self.factor_a) for attr in ['x', 'y']: self.scale_attr_val(element, attr, ['%'], 1.0 / self.factor_a) # set preserved transforms on top-level elements if width_scale != 1.0 and height_scale != 1.0: mat = simpletransform.parseTransform( 'scale({},{})'.format(width_scale, height_scale)) simpletransform.applyTransformToNode(mat, element)
def effect(self): if len(self.options.ids) < 2: inkex.debug("This extension requires that you select two paths.") return self.prepareSelectionList() #center at (0,0) bbox = pathmodifier.computeBBox([self.patternNode]) mat = [[1, 0, -(bbox[0] + bbox[1]) / 2], [0, 1, -(bbox[2] + bbox[3]) / 2]] if self.options.vertical: bbox = [-bbox[3], -bbox[2], bbox[0], bbox[1]] mat = simpletransform.composeTransform([[0, -1, 0], [1, 0, 0]], mat) mat[1][2] += self.options.noffset simpletransform.applyTransformToNode(mat, self.patternNode) width = bbox[1] - bbox[0] dx = width + self.options.space for skelnode in self.skeletons.itervalues(): self.curSekeleton = cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: self.skelcomp, self.lengths = linearize(comp) #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! self.skelcompIsClosed = (self.skelcomp[0] == self.skelcomp[-1]) length = sum(self.lengths) if self.options.stretch: dx = width + self.options.space n = int( (length - self.options.toffset + self.options.space) / dx) if n > 0: dx = (length - self.options.toffset) / n xoffset = self.skelcomp[0][0] - bbox[0] + self.options.toffset yoffset = self.skelcomp[0][1] - ( bbox[2] + bbox[3]) / 2 - self.options.noffset s = self.options.toffset while s <= length: mat = self.localTransformAt(s, self.options.follow) clone = copy.deepcopy(self.patternNode) #!!!--> should it be given an id? #seems to work without this!?! myid = self.patternNode.tag.split('}')[-1] clone.set("id", self.uniqueId(myid)) self.gNode.append(clone) simpletransform.applyTransformToNode(mat, clone) s += dx self.patternNode.getparent().remove(self.patternNode)
def update_layer_xform(self, settings): scale = ( TransformMatrix.translate(settings.origin) * TransformMatrix.scale(settings.scaleFactor) * TransformMatrix.translate(-settings.origin) ) mat = (scale * TransformMatrix.translate(settings.translation)).toSVG() for layer in [settings.markingsLayer, settings.layer]: for node in self.layer_contents(layer): simpletransform.applyTransformToNode(mat, node)
def safelyMoveTo(self, node, parent, doCopy = False): ''' Move a node, preserving its position in absolute coordinates ''' oldParentTr = SpeleoTransform.getTotalTransform(node.getparent()) newParentTr = SpeleoTransform.getTotalTransform(parent) if doCopy: node = copy.deepcopy(node) simpletransform.applyTransformToNode(oldParentTr, node) simpletransform.applyTransformToNode(SpeleoTransform.invertTransform(newParentTr), node) parent.append(node) return node
def effect(self): if len(self.options.ids)<2: inkex.debug("This extension requires that you select two paths.") return self.prepareSelectionList() #center at (0,0) bbox=pathmodifier.computeBBox([self.patternNode]) mat=[[1,0,-(bbox[0]+bbox[1])/2],[0,1,-(bbox[2]+bbox[3])/2]] if self.options.vertical: bbox=[-bbox[3],-bbox[2],bbox[0],bbox[1]] mat=simpletransform.composeTransform([[0,-1,0],[1,0,0]],mat) mat[1][2] += self.options.noffset simpletransform.applyTransformToNode(mat,self.patternNode) width=bbox[1]-bbox[0] dx=width+self.options.space for skelnode in self.skeletons.itervalues(): self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: self.skelcomp,self.lengths=linearize(comp) #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1]) length=sum(self.lengths) if self.options.stretch: dx=width+self.options.space n=int((length-self.options.toffset+self.options.space)/dx) if n>0: dx=(length-self.options.toffset)/n xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset s=self.options.toffset while s<=length: mat=self.localTransformAt(s,self.options.follow) clone=copy.deepcopy(self.patternNode) #!!!--> should it be given an id? #seems to work without this!?! myid = self.patternNode.tag.split('}')[-1] clone.set("id", self.uniqueId(myid)) self.gNode.append(clone) simpletransform.applyTransformToNode(mat,clone) s+=dx self.patternNode.getparent().remove(self.patternNode)
def place(self, nodes): max_line_width = self.unittouu('450mm') x_gap = y_gap = self.unittouu('10mm') x_start = self.unittouu('3mm') y_start = self.unittouu('1600mm') - self.unittouu('3mm') total_width = 0 total_height = 0 line_nodes = [] group = etree.SubElement(self.current_layer, addNS('g', 'svg')) for id, node, bbox in nodes: x, _, y, _ = bbox node_width = x_gap + self.width(bbox) # reached end of line, reset, move higher, start new group if total_width + node_width > max_line_width: group = etree.SubElement(self.current_layer, addNS('g', 'svg')) total_width = 0 total_height += self.height( self.computeBBox(line_nodes)) + y_gap line_nodes = [] group.append(node) x_dest = x_start + total_width y_dest = y_start - (total_height + self.height(bbox)) if node.tag == addNS('path', 'svg'): x_delta = x_dest - x y_delta = y_dest - y path = parsePath(node.attrib['d']) translatePath(path, x_delta, y_delta) node.attrib['d'] = formatPath(path) elif node.tag == addNS('g', 'svg'): x_delta = x_dest - x y_delta = y_dest - y translation_matrix = [[1.0, 0.0, x_delta], [0.0, 1.0, y_delta]] applyTransformToNode(translation_matrix, node) else: node.attrib['x'] = str(x_dest) node.attrib['y'] = str(y_dest) total_width += node_width line_nodes.append(node)
def place(self, nodes): max_line_width = self.unittouu('450mm') x_gap = y_gap = self.unittouu('10mm') x_start = self.unittouu('3mm') y_start = self.unittouu('1600mm') - self.unittouu('3mm') total_width = 0 total_height = 0 line_nodes = [] group = etree.SubElement(self.current_layer, addNS('g','svg')) for id, node, bbox in nodes: x, _, y, _ = bbox node_width = x_gap + self.width(bbox) # reached end of line, reset, move higher, start new group if total_width + node_width > max_line_width: group = etree.SubElement(self.current_layer, addNS('g','svg')) total_width = 0 total_height += self.height(self.computeBBox(line_nodes)) + y_gap line_nodes = [] group.append(node) x_dest = x_start + total_width y_dest = y_start - (total_height + self.height(bbox)) if node.tag == addNS('path','svg'): x_delta = x_dest - x y_delta = y_dest - y path = parsePath(node.attrib['d']) translatePath(path, x_delta, y_delta) node.attrib['d'] = formatPath(path) elif node.tag == addNS('g','svg'): x_delta = x_dest - x y_delta = y_dest - y translation_matrix = [[1.0, 0.0, x_delta], [0.0, 1.0, y_delta]] applyTransformToNode(translation_matrix, node) else: node.attrib['x'] = str(x_dest) node.attrib['y'] = str(y_dest) total_width += node_width line_nodes.append(node)
def translateElement(self, node, x, y, relative=False): # Grab transform attribute if it exists. transform = node.get("transform", "") # Compute the nodes bounding box box = list(simpletransform.computeBBox([node])) pos_x = box[0] pos_y = box[2] # rotation center is not a breeze to calculate from the matrix, so thanks inkscape ;) origin_x = float(node.get(inkex.addNS("transform-center-x", "inkscape"), 0)) origin_y = float(node.get(inkex.addNS("transform-center-y", "inkscape"), 0)) origin_x = origin_x + (box[1] / 2) origin_y = (origin_y * -1) + (box[3] / 2) if transform == "": # If there is no transform attribute on the node we add one node.attrib["transform"] = "" # simpletransform returns a multi dim array of matrix values transform = simpletransform.parseTransform(transform) transformObject = self.normalizeMatrix(transform) inkex.debug(transformObject) # offset_x = (transform[0][2]-pos_x) # offset_y = (transform[1][2]-pos_y) offset_x = pos_x * -1 offset_y = pos_y * -1 inkex.debug([offset_x, offset_y]) transform = simpletransform.parseTransform( ("translate(" + str(offset_x) + " " + str(offset_y) + ")"), transform ) transformObject = self.normalizeMatrix(transform) inkex.debug(transformObject) inkex.debug(transform) if relative == False: matrix = simpletransform.formatTransform(transform) node.set("transform", matrix) inkex.debug(matrix) else: simpletransform.applyTransformToNode(transform, node)
def fill_row(self, node): max_line_width = self.unittouu('450mm') x_gap = y_gap = self.unittouu('10mm') x_start = self.unittouu('3mm') y_start = self.unittouu('1600mm') - self.unittouu('3mm') total_width = 0 total_height = self.total_height group = etree.SubElement(self.current_layer, addNS('g', 'svg')) bbox = computeBBox([node]) x, _, y, _ = bbox node_width = x_gap + self.width(bbox) while total_width + node_width < max_line_width: node_copy = deepcopy(node) group.append(node_copy) x_dest = x_start + total_width y_dest = y_start - (total_height + self.height(bbox)) # translation logic if node_copy.tag == addNS('path', 'svg'): x_delta = x_dest - x y_delta = y_dest - y path = parsePath(node_copy.attrib['d']) translatePath(path, x_delta, y_delta) node_copy.attrib['d'] = formatPath(path) elif node_copy.tag == addNS('g', 'svg'): x_delta = x_dest - x y_delta = y_dest - y translation_matrix = [[1.0, 0.0, x_delta], [0.0, 1.0, y_delta]] applyTransformToNode(translation_matrix, node_copy) else: node_copy.attrib['x'] = str(x_dest) node_copy.attrib['y'] = str(y_dest) total_width += node_width self.total_height += self.height(computeBBox(group)) + y_gap
def fill_row(self, node): max_line_width = self.unittouu('450mm') x_gap = y_gap = self.unittouu('10mm') x_start = self.unittouu('3mm') y_start = self.unittouu('1600mm') - self.unittouu('3mm') total_width = 0 total_height = self.total_height group = etree.SubElement(self.current_layer, addNS('g','svg')) bbox = computeBBox([node]) x, _, y, _ = bbox node_width = x_gap + self.width(bbox) while total_width + node_width < max_line_width: node_copy = deepcopy(node) group.append(node_copy) x_dest = x_start + total_width y_dest = y_start - (total_height + self.height(bbox)) # translation logic if node_copy.tag == addNS('path','svg'): x_delta = x_dest - x y_delta = y_dest - y path = parsePath(node_copy.attrib['d']) translatePath(path, x_delta, y_delta) node_copy.attrib['d'] = formatPath(path) elif node_copy.tag == addNS('g','svg'): x_delta = x_dest - x y_delta = y_dest - y translation_matrix = [[1.0, 0.0, x_delta], [0.0, 1.0, y_delta]] applyTransformToNode(translation_matrix, node_copy) else: node_copy.attrib['x'] = str(x_dest) node_copy.attrib['y'] = str(y_dest) total_width += node_width self.total_height += self.height(computeBBox(group)) + y_gap
def draw_SVG_text(x, y, text, parent, style, angle=0): attribs = { 'style' : simplestyle.formatStyle(style), 'x' : str(x), 'y' : str(y) } # Generate text txt = inkex.etree.SubElement(parent, inkex.addNS('text'), attribs) txt.text = text # Rotate (if needed) # We need to rotate around the text center. # To achieve this we move it to the origin, rotate it and then translate it back rotmatrix = simpletransform.parseTransform('translate('+str(x)+','+str(y)+')'+ ' rotate('+str(angle)+')'+ ' translate('+str(-x)+','+str(-y)+')') simpletransform.applyTransformToNode(rotmatrix, txt) return txt
def fromSVG(self,nodes): # takes in a list of lxml elements # returns a list of inkscape compound simplepaths (paths in paths etc...) # could possibly push up into Plot spl = [] for node in nodes: tag = node.tag[node.tag.rfind("}")+1:] if tag == 'path': spl.extend(simplepath.parsePath(node.get("d"))) elif tag == 'rect': # how do I convert rect to path?? raise AssertionError("Cannot handle '%s' objects, covert to rect's to path first."%(tag)) elif tag == 'g': if node.get("transform"): simpletransform.applyTransformToNode(node.get("transform"),node) spl.extend(self.fromSVG(list(node))) else: raise AssertionError("Cannot handle tag '%s'"%(tag)) return spl
def unpackLayers(self, node, transform, appliedTransforms): ''' Unpack a group back into layers and apply a transform accordingly ''' # Was that a layer before going through packLayers() ? cName = node.get("class") if cName <> None: if cName == "wasLayer": # It seems so! # Revert changes made by packLayers() node.set(inkex.addNS('groupmode', 'inkscape'), "layer") node.attrib.pop("class") # The group could have acquired its own transform... layerTransform = node.get("transform") # Save transform applied to this layer, in case it is used by <use> appliedTransforms[node.get("id")] = transform # Transforms on regular groups are nice, but we do not want to have a transform on a layer! if layerTransform <> None: # Remove the transform node.attrib.pop("transform") # Compose it with what we have transform = simpletransform.composeTransform( transform, simpletransform.parseTransform(layerTransform)) # Transform all child nodes of this layer, unpacking sub-layers if there are any for child in node: self.unpackLayers(child, transform, appliedTransforms) return # We can simply apply our transform and say goodbye! simpletransform.applyTransformToNode(transform, node) # Save transform applied to this object, in case it is used by <use> appliedTransforms[node.get("id")] = transform
def effect(self): # 選択要素がなければ終了 if len(self.selected) <= 0: return # 親ノード parentnode = self.current_layer # 選択要素を取得 sel = self.selected # inkex.debug('>> ' + ' '.join(_(v) for v in sel)) # 変形マトリクスの作成 transformation = 'scale(-1, 1)' transform = simpletransform.parseTransform(transformation) # 複製と変形マトリクスの適用 for id, node in sel.iteritems(): childNode = deepcopy(node) parentnode.append(childNode) simpletransform.applyTransformToNode(transform, childNode)
def draw_SVG_text(x, y, text, parent, style, angle=0): attribs = { 'style': simplestyle.formatStyle(style), 'x': str(x), 'y': str(y) } # Generate text txt = inkex.etree.SubElement(parent, inkex.addNS('text'), attribs) txt.text = text # Rotate (if needed) # We need to rotate around the text center. # To achieve this we move it to the origin, rotate it and then translate it back rotmatrix = simpletransform.parseTransform('translate(' + str(x) + ',' + str(y) + ')' + ' rotate(' + str(angle) + ')' + ' translate(' + str(-x) + ',' + str(-y) + ')') simpletransform.applyTransformToNode(rotmatrix, txt) return txt
def fromSVG(self, nodes, color): # takes in a list of lxml elements # returns a list of inkscape compound simplepaths (paths in paths etc...) # could possibly push up into Plot spl = [] for node in nodes: tag = node.tag[node.tag.rfind("}") + 1:] if tag == 'path': # spl.extend(simplepath.parsePath(node.get("d"))) #Cut by color style_str = node.get('style') if style_str: style = simplestyle.parseStyle(style_str) if 'fill' in style: f = style['fill'] color = str(color) color_hex = color[-7:] if (f == str(color_hex) or str(color_hex) == '#######'): spl.extend(simplepath.parsePath(node.get("d"))) #/Cut by color elif tag == 'rect': # how do I convert rect to path?? raise AssertionError( "Cannot handle '%s' objects, covert to rect's to path first." % (tag)) elif tag == 'g': if node.get("transform"): simpletransform.applyTransformToNode( node.get("transform"), node) spl.extend(self.fromSVG(list(node))) else: raise AssertionError("Cannot handle tag '%s'" % (tag)) if (len(spl) == 0): raise AssertionError("No paths!", "Last selected color: " + color) sys.exit(0) return spl
def effect(self): pm = PathModifier() pm.document = self.document for nid, node in self.selected.iteritems(): # set() removes duplicates angles = set( # and remove Nones [x for x in rotate_helper.optimal_rotations(node) if x is not None]) # Go backwards so we know if we need to duplicate the node for # multiple rotations. (We don't want to rotate the main node # before duplicating it.) for i, angle in reversed(list(enumerate(angles))): if i > 0: # Rotate a duplicate of the node rotate_node = pm.duplicateNodes({nid: node}).items()[0][1] else: rotate_node = node simpletransform.applyTransformToNode( rotate_helper.rotate_matrix(rotate_node, angle), rotate_node)
def fromSVG(self, nodes): # takes in a list of lxml elements # returns a list of inkscape compound simplepaths (paths in paths etc...) # could possibly push up into Plot spl = [] for node in nodes: tag = node.tag[node.tag.rfind("}") + 1:] if tag == 'path': spl.extend(simplepath.parsePath(node.get("d"))) elif tag == 'rect': # how do I convert rect to path?? raise AssertionError( "Cannot handle '%s' objects, covert to rect's to path first." % (tag)) elif tag == 'g': if node.get("transform"): simpletransform.applyTransformToNode( node.get("transform"), node) spl.extend(self.fromSVG(list(node))) else: raise AssertionError("Cannot handle tag '%s'" % (tag)) return spl
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 create_pattern(self, rxy, cxy, angle, parent): # radius vars (rx, ry) = rxy # center vars (cx, cy) = cxy # pattern style style = { 'stroke': '#000000', 'stroke-width': '0', 'fill': '#000000', 'fill-opacity': '1.0' } # pattern element attributes attribs = { 'style': simplestyle.formatStyle(style), 'rx': str(rx), 'ry': str(ry), 'cx': str(cx), 'cy': str(cy) } # create an xml element for the pattern el = inkex.etree.SubElement(parent, inkex.addNS('ellipse', 'svg'), attribs) # rotate the pattern to mimic calligraphy pen transformation = 'rotate(' + str(angle) + ',' + str(cx) + ',' + str( cy) + ')' transform = simpletransform.parseTransform(transformation) simpletransform.applyTransformToNode(transform, el) return el
def processTree(self, node): ''' Recursively walk the SVG tree and randomize all rock/pebble symbols on the way ''' # Is this a symbol reference? if node.tag == inkex.addNS('use', 'svg'): # Is this one of our rock/pebble symbols? m = re.match('#(gr|un|)?([ra])b([0-9]+)[a-z]', str(node.get(inkex.addNS("href", "xlink")))) if m: # Add translation, if present x = float(node.get("x")) y = float(node.get("y")) if x <> 0 or y <> 0: node.set("x", "0") node.set("y", "0") currentTr = node.get("transform") if currentTr == None: currentTr = "" node.set("transform", currentTr + (" translate(%.6f, %.6f) " % (x, y))) # Get current symbol transform tr = SpeleoTransform.getTotalTransform(node) # Move it back to 0,0 for rotation simpletransform.applyTransformToNode(SpeleoTransform.invertTransform(tr), node) # Select a new, random symbol ID (matching the symbol family) new_id = m.group(1) + m.group(2) + "b" + m.group(3) + random.choice("abcdefghij") # Make sure the new symbol type is with us if self.ensureSymbol(new_id): node.set(inkex.addNS("href", "xlink"), "#" + new_id) # If not, we just leave the type as it is. # Apply random rotation simpletransform.applyTransformToNode(simpletransform.parseTransform("rotate(" + str(random.randint(0, 359)) + ")"), node) # Return the symbol to where it was simpletransform.applyTransformToNode(tr, node) # For compatibility with old maps, using speleoUIS3 if (node.tag == inkex.addNS('tspan', 'svg') or node.tag == inkex.addNS('text', 'svg')) and node.text: if len(node.text) == 1: if node.text in string.ascii_lowercase: node.text = random.choice(string.ascii_lowercase) elif node.text in string.ascii_uppercase: node.text = random.choice(string.ascii_uppercase) if (node.text in string.ascii_letters): node.set("rotate", str(random.randint(0, 359))) # Recurse! for child in node: self.processTree(child);
def effect(self): pts = [] for node in self.selected.itervalues(): if node.tag == inkex.addNS('path','svg'): guide = node pts = get_n_points_from_path(node, 2) if len(pts) == 2: (x0, y0), (x1, y1) = pts theta = atan2(y1-y0, x1-x0)*180./pi length = ((x1-x0)**2 + (y1-y0)**2)**0.5 label = inkex.etree.SubElement(self.current_layer, 'g') labeltag = inkex.etree.SubElement(label, 'g') if theta <= -90.0 or theta > 90.0: text, tw, th = self.make_text(anchor='end') applyTransformToNode(parseTransform('rotate(180.0)'), text) else: text, tw, th = self.make_text(anchor='start') fs = float(self.options.font_size) kh = 1.05 h = kh*fs pad = (h - fs)*0.5 + 0.04*tw w = tw + pad*2 x = -pad + 0.07*fs y = -0.5*h box = self.make_box(x, y, w, h, r=0.25*min(w, h)) labeltag.append(box) labeltag.append(text) transform = 'translate(%f, 0.0)'% (length,) applyTransformToNode(parseTransform(transform), labeltag) leader = self.make_double_line(length+x) label.append(leader) transform = 'translate(%f, %f) rotate(%f)'%(x0, y0, theta) applyTransformToNode(parseTransform(transform), label) guide.getparent().remove(guide)
def effect(self): pts = [] for node in self.selected.itervalues(): if node.tag == inkex.addNS('path', 'svg'): guide = node pts = get_n_points_from_path(node, 2) if len(pts) == 2: (x0, y0), (x1, y1) = pts theta = atan2(y1 - y0, x1 - x0) * 180. / pi length = ((x1 - x0)**2 + (y1 - y0)**2)**0.5 label = inkex.etree.SubElement(self.current_layer, 'g') labeltag = inkex.etree.SubElement(label, 'g') if theta <= -90.0 or theta > 90.0: text, tw, th = self.make_text(anchor='end') applyTransformToNode(parseTransform('rotate(180.0)'), text) else: text, tw, th = self.make_text(anchor='start') fs = float(self.options.font_size) kh = 1.05 h = kh * fs pad = (h - fs) * 0.5 + 0.04 * tw w = tw + pad * 2 x = -pad + 0.07 * fs y = -0.5 * h box = self.make_box(x, y, w, h, r=0.25 * min(w, h)) labeltag.append(box) labeltag.append(text) transform = 'translate(%f, 0.0)' % (length, ) applyTransformToNode(parseTransform(transform), labeltag) leader = self.make_double_line(length + x) label.append(leader) transform = 'translate(%f, %f) rotate(%f)' % (x0, y0, theta) applyTransformToNode(parseTransform(transform), label) guide.getparent().remove(guide)
def effect(self): if len(self.options.ids) < 2: inkex.errormsg(_("This extension requires two selected paths.")) return self.prepareSelectionList() #center at (0,0) bbox = pathmodifier.computeBBox([self.patternNode]) mat = [[1, 0, -(bbox[0] + bbox[1]) / 2], [0, 1, -(bbox[2] + bbox[3]) / 2]] if self.options.vertical: bbox = [-bbox[3], -bbox[2], bbox[0], bbox[1]] mat = simpletransform.composeTransform([[0, -1, 0], [1, 0, 0]], mat) mat[1][2] += self.options.noffset simpletransform.applyTransformToNode(mat, self.patternNode) width = bbox[1] - bbox[0] dx = width + self.options.space #check if group and expand it patternList = [] if self.options.grouppick and (self.patternNode.tag == inkex.addNS( 'g', 'svg') or self.patternNode.tag == 'g'): mat = simpletransform.parseTransform( self.patternNode.get("transform")) for child in self.patternNode: simpletransform.applyTransformToNode(mat, child) patternList.append(child) else: patternList.append(self.patternNode) #inkex.debug(patternList) counter = 0 for skelnode in self.skeletons.itervalues(): self.curSekeleton = cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: self.skelcomp, self.lengths = linearize(comp) #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! self.skelcompIsClosed = (self.skelcomp[0] == self.skelcomp[-1]) length = sum(self.lengths) if self.options.stretch: dx = width + self.options.space n = int( (length - self.options.toffset + self.options.space) / dx) if n > 0: dx = (length - self.options.toffset) / n xoffset = self.skelcomp[0][0] - bbox[0] + self.options.toffset yoffset = self.skelcomp[0][1] - ( bbox[2] + bbox[3]) / 2 - self.options.noffset s = self.options.toffset while s <= length: mat = self.localTransformAt(s, self.options.follow) if self.options.pickmode == "rand": clone = copy.deepcopy(patternList[random.randint( 0, len(patternList) - 1)]) if self.options.pickmode == "seq": clone = copy.deepcopy(patternList[counter]) counter = (counter + 1) % len(patternList) #!!!--> should it be given an id? #seems to work without this!?! myid = patternList[random.randint(0, len(patternList) - 1)].tag.split('}')[-1] clone.set("id", self.uniqueId(myid)) self.gNode.append(clone) simpletransform.applyTransformToNode(mat, clone) s += dx self.patternNode.getparent().remove(self.patternNode)
def effect(self): #used in cycles scale_len_inc = self.options.in_length scale_len_dec = self.options.in_length scale_width_inc = self.options.in_width scale_width_dec = self.options.in_width #horizontal distance is set by user horiz = self.options.hor_dist #vertical is just to keep details on the same lines vert = (-20 / 3) * 2 if self.selected: for id, node in self.selected.iteritems(): #saving original for decreasing cycle initial_node = node #increasing sizes from current for n in range(self.options.in_size, self.options.out_max_size): #calculating length factor scale_len_next = scale_len_inc + 20 / 3 scale_factor_length = scale_len_next / scale_len_inc scale_len_inc = scale_len_next #calculating width factor scale_width_next = scale_width_inc + 1 scale_factor_width = scale_width_next / scale_width_inc scale_width_inc = scale_width_next #initializing tranformations #horizontal transformation str_hor_translation = 'translate(' + str( self.unittouu(str(horiz) + "mm")) + ', ' + str( self.unittouu(str(vert) + "mm")) + ')' horiz_translation = simpletransform.parseTransform( str_hor_translation) #length transformation str_scaling_length = 'scale(' + str( scale_factor_length) + ')' scaling_length = simpletransform.parseTransform( str_scaling_length) #width transformation str_scaling_width = 'scale(' + str( scale_factor_width) + ')' scaling_width = simpletransform.parseTransform( str_scaling_width) #copying previous size and then applying transformation new_node = copy.deepcopy(node) #changing length simpletransform.applyTransformToNode( scaling_length, new_node) #changing width simpletransform.applyTransformToNode( scaling_width, new_node) #moving horizontally simpletransform.applyTransformToNode( horiz_translation, new_node) #inserting detail in current layer self.current_layer.append(new_node) node = new_node #decreasing sizes from current for n in range(self.options.out_min_size, self.options.in_size): scale_len_prev = scale_len_dec - 20 / 3 scale_factor_length = scale_len_prev / scale_len_dec scale_len_dec = scale_len_prev scale_width_prev = scale_width_dec - 1 scale_factor_width = scale_width_prev / scale_width_dec scale_width_dec = scale_width_prev str_hor_translation = 'translate(' + str( self.unittouu(str((-1) * horiz) + "mm")) + ', ' + str( self.unittouu(str((-1) * vert) + "mm")) + ')' horiz_translation = simpletransform.parseTransform( str_hor_translation) str_scaling_length = 'scale(' + str( scale_factor_length) + ')' scaling_length = simpletransform.parseTransform( str_scaling_length) str_scaling_width = 'scale(' + str( scale_factor_width) + ')' scaling_width = simpletransform.parseTransform( str_scaling_width) new_node = copy.deepcopy(initial_node) simpletransform.applyTransformToNode( scaling_length, new_node) simpletransform.applyTransformToNode( scaling_width, new_node) simpletransform.applyTransformToNode( horiz_translation, new_node) self.current_layer.append(new_node) initial_node = new_node
def effect(self): if len(self.options.ids)<2: inkex.errormsg(_("This extension requires two selected paths.")) return self.prepareSelectionList() #center at (0,0) bbox=pathmodifier.computeBBox([self.patternNode]) mat=[[1,0,-(bbox[0]+bbox[1])/2],[0,1,-(bbox[2]+bbox[3])/2]] if self.options.vertical: bbox=[-bbox[3],-bbox[2],bbox[0],bbox[1]] mat=simpletransform.composeTransform([[0,-1,0],[1,0,0]],mat) mat[1][2] += self.options.noffset simpletransform.applyTransformToNode(mat,self.patternNode) width=bbox[1]-bbox[0] dx=width+self.options.space #check if group and expand it patternList = [] if self.options.grouppick and (self.patternNode.tag == inkex.addNS('g','svg') or self.patternNode.tag=='g') : mat=simpletransform.parseTransform(self.patternNode.get("transform")) for child in self.patternNode: simpletransform.applyTransformToNode(mat,child) patternList.append(child) else : patternList.append(self.patternNode) #inkex.debug(patternList) counter=0 for skelnode in self.skeletons.itervalues(): self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) for comp in self.curSekeleton: self.skelcomp,self.lengths=linearize(comp) #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1]) length=sum(self.lengths) if self.options.stretch: dx=width+self.options.space n=int((length-self.options.toffset+self.options.space)/dx) if n>0: dx=(length-self.options.toffset)/n xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset s=self.options.toffset while s<=length: mat=self.localTransformAt(s,self.options.follow) if self.options.pickmode=="rand": clone=copy.deepcopy(patternList[random.randint(0, len(patternList)-1)]) if self.options.pickmode=="seq": clone=copy.deepcopy(patternList[counter]) counter=(counter+1)%len(patternList) #!!!--> should it be given an id? #seems to work without this!?! myid = patternList[random.randint(0, len(patternList)-1)].tag.split('}')[-1] clone.set("id", self.uniqueId(myid)) self.gNode.append(clone) simpletransform.applyTransformToNode(mat,clone) s+=dx self.patternNode.getparent().remove(self.patternNode)
def effect(self): for node in self.selected.values(): min_width_angle = rotate_helper.optimal_rotations(node)[0] if min_width_angle is not None: simpletransform.applyTransformToNode( rotate_helper.rotate_matrix(node, min_width_angle), node)
def beVerbose(self, dictCone, unitFactor, parent): """ Verbose output of calculated values. Can be used for debugging purposes or if calculated values needed. """ # unpack base_dia = dictCone['diaBase'] cut_dia = dictCone['diaCut'] cone_height = dictCone['heightCone'] shortradius = dictCone['shortRadius'] longradius = dictCone['longRadius'] angle = dictCone['angle'] chord_base = dictCone['chordBase'] chord_cut = dictCone['chordCut'] ptA = dictCone['ptA'] ptB = dictCone['ptB'] ptC = dictCone['ptC'] ptD = dictCone['ptD'] # styles for markup stroke_width = max( 0.1, self.getUnittouu( str(self.options.strokeWidth / 2) + self.options.units)) line_style = { 'stroke': self.color_marker_dim, 'stroke-width': str(stroke_width), 'fill': 'none' } arrow_style = self.dimline_style font_height = min( 32, max( 8, int(self.getUnittouu( str(longradius / 40) + self.options.units)))) text_style = { 'font-size': str(font_height), 'font-family': 'arial', 'text-anchor': 'middle', 'text-align': 'center', 'fill': self.color_marker_dim } # verbose message for debug window msg = "Base diameter: " + str(base_dia) + "Cut diameter: " + str(cut_dia) + \ "\nCone height: " + str(cone_height) + "\nShort radius: " + str(shortradius) + \ "\nLong radius: " + str(longradius) + "\nAngle of circle sector: " + str(angle) + \ " radians (= " + str(math.degrees(angle)) + " degrees)" + \ "\nChord length of base arc: " + str(chord_base) + \ "\nChord length of cut arc: " + str(chord_cut) #inkex.debug( msg) # Mark center marker_length = max(5, longradius * unitFactor / 100) line_attribs = { 'style': simplestyle.formatStyle(line_style), inkex.addNS('label', 'inkscape'): 'center', 'd': 'M -{0},-{0} L {0},{0}'.format(marker_length) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) line_attribs = { 'style': simplestyle.formatStyle(line_style), inkex.addNS('label', 'inkscape'): 'center', 'd': 'M -{0},{0} L {0},-{0}'.format(marker_length) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) # Draw tick marks line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M 0,-3 L 0,-30' } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) if cut_dia != 0: line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M {0},-3 L {0},-30'.format(shortradius * unitFactor) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M {0},-3 L {0},-30'.format(longradius * unitFactor) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) # span line arrow_style['stroke'] = self.color_marker_dim self.drawDimension((0, -10), (shortradius * unitFactor, -10), arrow_style, parent) self.drawDimension((shortradius * unitFactor, -10), (longradius * unitFactor, -10), arrow_style, parent) # labels for short, long radii if cut_dia >= 0.001: text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': str(shortradius * unitFactor / 2), 'y': str(-15) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" % (shortradius) text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': str( (shortradius + (longradius - shortradius) / 2) * unitFactor), 'y': str(-15) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" % (longradius) # Draw angle lowside = math.degrees(angle) < 180 value = math.degrees(angle) if lowside else 360 - math.degrees(angle) # radial limit lines line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M 3,0 L %4.2f,0' % (ptA[0] * unitFactor * 0.8) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M %4.2f,%4.2f L %4.2f,%4.2f' % (ptD[0] * unitFactor * 0.02, ptD[1] * unitFactor * 0.02, ptD[0] * unitFactor * 0.8, ptD[1] * unitFactor * 0.8) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) # arc arc_rad = ptA[0] * unitFactor * 0.50 gap = self.getUnittouu(str(font_height * 2) + "pt") textpos = self.drawDimArc((0, 0), 0, value, arc_rad, arrow_style, parent, gap, lowside) # angle label textpos[1] += font_height / 4 if lowside else font_height / 2 text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': str(textpos[0]), 'y': str(textpos[1]) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.2f deg" % (value) # chord lines dash_style = deepcopy(arrow_style) dash_style['stroke'] = self.color_marker_chords dash_style['stroke-dasharray'] = '4, 2, 1, 2' line = self.drawDimension((ptA[0] * unitFactor, ptA[1] * unitFactor), (ptD[0] * unitFactor, ptD[1] * unitFactor), dash_style, parent) line = self.drawDimension((ptB[0] * unitFactor, ptB[1] * unitFactor), (ptC[0] * unitFactor, ptC[1] * unitFactor), dash_style, parent) # chord labels centerx = ptB[0] * unitFactor + (ptC[0] - ptB[0]) * unitFactor / 2 centery = ptB[1] * unitFactor + (ptC[1] - ptB[1]) * unitFactor / 2 line_angle = calc_angle_between_points(ptC, ptB) ypos = centery + font_height + 2 if line_angle < 0 else centery - 2 text_style['fill'] = self.color_marker_chords text_atts = { 'style': simplestyle.formatStyle(text_style), 'transform': 'rotate(%f)' % (line_angle) } text = inkex.etree.SubElement(parent, 'text', text_atts) scale_matrix = [[1, 0.0, centerx], [0.0, 1, ypos]] # needs cos,sin corrections simpletransform.applyTransformToNode(scale_matrix, text) text.text = "%4.2f" % (chord_base) if cut_dia >= 0.001: centerx = ptA[0] * unitFactor + (ptD[0] - ptA[0]) * unitFactor / 2 centery = ptA[1] * unitFactor + (ptD[1] - ptA[1]) * unitFactor / 2 xpos = centerx - font_height * math.sin( math.radians(abs(line_angle))) ypos = centery - 2 if line_angle > 0 else centery + font_height + 2 text = inkex.etree.SubElement(parent, 'text', text_atts) scale_matrix = [[1, 0.0, centerx], [0.0, 1, ypos]] simpletransform.applyTransformToNode(scale_matrix, text) text.text = "%4.2f" % (chord_cut) # frustum lines frustrum_repos = [[1, 0.0, 1], [ 0.0, 1, math.sqrt( pow(shortradius * unitFactor, 2) - pow(cut_dia * unitFactor / 2, 2)) ]] text_style['fill'] = self.color_marker_base line_style['stroke'] = self.color_marker_base arrow_style['stroke'] = self.color_marker_base line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M %f,%f L %f,%f %f,%f %f,%f z' % (-cut_dia / 2 * unitFactor, 0, cut_dia / 2 * unitFactor, 0, base_dia / 2 * unitFactor, cone_height * unitFactor, -base_dia / 2 * unitFactor, cone_height * unitFactor) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) simpletransform.applyTransformToNode(frustrum_repos, line) # ticks line_attribs = { 'style': simplestyle.formatStyle(line_style), 'd': 'M %f,%f L %f,%f' % (-(5 + cut_dia / 2 * unitFactor), 0, -(5 + base_dia / 2 * unitFactor), 0) } line = inkex.etree.SubElement(parent, inkex.addNS('path', 'svg'), line_attribs) simpletransform.applyTransformToNode(frustrum_repos, line) # line = self.drawDimension( (-base_dia / 2 * unitFactor, 0), (-base_dia / 2 * unitFactor, cone_height * unitFactor), arrow_style, parent) simpletransform.applyTransformToNode(frustrum_repos, line) # frustum text text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': str(-(18 + base_dia / 2 * unitFactor)), 'y': str(cone_height * unitFactor / 2) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" % (cone_height) simpletransform.applyTransformToNode(frustrum_repos, text) if cut_dia >= 0.001: text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': '0', 'y': str(font_height) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" % (cut_dia) simpletransform.applyTransformToNode(frustrum_repos, text) text_atts = { 'style': simplestyle.formatStyle(text_style), 'x': '0', 'y': str(cone_height * unitFactor + font_height) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" % (base_dia) simpletransform.applyTransformToNode(frustrum_repos, text)
def beVerbose(self, dictCone, unitFactor, parent): """ Verbose output of calculated values. Can be used for debugging purposes or if calculated values needed. """ # unpack base_dia = dictCone['diaBase'] cut_dia = dictCone['diaCut'] cone_height = dictCone['heightCone'] shortradius = dictCone['shortRadius'] longradius = dictCone['longRadius'] angle = dictCone['angle'] chord_base = dictCone['chordBase'] chord_cut = dictCone['chordCut'] ptA = dictCone['ptA'] ptB = dictCone['ptB'] ptC = dictCone['ptC'] ptD = dictCone['ptD'] # styles for markup stroke_width = max(0.1, self.getUnittouu(str(self.options.strokeWidth/2) + self.options.units)) line_style = { 'stroke': self.color_marker_dim, 'stroke-width': str(stroke_width), 'fill':'none' } arrow_style = self.dimline_style font_height = min(32, max( 8, int(self.getUnittouu(str(longradius/40) + self.options.units)))) text_style = { 'font-size': str(font_height), 'font-family': 'arial', 'text-anchor': 'middle', 'text-align': 'center', 'fill': self.color_marker_dim } # verbose message for debug window msg = "Base diameter: " + str(base_dia) + "Cut diameter: " + str(cut_dia) + \ "\nCone height: " + str(cone_height) + "\nShort radius: " + str(shortradius) + \ "\nLong radius: " + str(longradius) + "\nAngle of circle sector: " + str(angle) + \ " radians (= " + str(math.degrees(angle)) + " degrees)" + \ "\nChord length of base arc: " + str(chord_base) + \ "\nChord length of cut arc: " + str(chord_cut) #inkex.debug( msg) # Mark center marker_length = max(5, longradius* unitFactor/100) line_attribs = {'style' : simplestyle.formatStyle(line_style), inkex.addNS('label','inkscape') : 'center', 'd' : 'M -{0},-{0} L {0},{0}'.format(marker_length)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) line_attribs = {'style' : simplestyle.formatStyle(line_style), inkex.addNS('label','inkscape') : 'center', 'd' : 'M -{0},{0} L {0},-{0}'.format(marker_length)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) # Draw tick marks line_attribs = {'style' : simplestyle.formatStyle(line_style), 'd' : 'M 0,-3 L 0,-30'} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) if cut_dia != 0: line_attribs = {'style' : simplestyle.formatStyle(line_style), 'd' : 'M {0},-3 L {0},-30'.format(shortradius * unitFactor)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) line_attribs = {'style' : simplestyle.formatStyle(line_style), 'd' : 'M {0},-3 L {0},-30'.format(longradius * unitFactor)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) # span line arrow_style['stroke'] = self.color_marker_dim self.drawDimension((0,-10), (shortradius * unitFactor, -10), arrow_style, parent) self.drawDimension((shortradius * unitFactor,-10), (longradius * unitFactor, -10), arrow_style, parent) # labels for short, long radii if cut_dia >= 0.001: text_atts = {'style':simplestyle.formatStyle(text_style), 'x': str(shortradius*unitFactor/2), 'y': str(-15) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" %(shortradius) text_atts = {'style':simplestyle.formatStyle(text_style), 'x': str((shortradius + (longradius-shortradius)/2)*unitFactor), 'y': str(-15) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" %(longradius) # Draw angle lowside = math.degrees(angle) < 180 value = math.degrees(angle) if lowside else 360-math.degrees(angle) # radial limit lines line_attribs = {'style' : simplestyle.formatStyle(line_style), 'd' : 'M 3,0 L %4.2f,0' % (ptA[0]*unitFactor*0.8)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) line_attribs = {'style' : simplestyle.formatStyle(line_style), 'd' : 'M %4.2f,%4.2f L %4.2f,%4.2f' % (ptD[0]*unitFactor*0.02, ptD[1]*unitFactor*0.02,ptD[0]*unitFactor*0.8, ptD[1]*unitFactor*0.8)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) # arc arc_rad = ptA[0]*unitFactor*0.50 gap = self.getUnittouu(str(font_height*2)+"pt") textpos = self.drawDimArc((0,0), 0, value, arc_rad, arrow_style, parent, gap, lowside) # angle label textpos[1] += font_height/4 if lowside else font_height/2 text_atts = {'style':simplestyle.formatStyle(text_style), 'x': str(textpos[0]), 'y': str(textpos[1]) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.2f deg" %(value) # chord lines dash_style = deepcopy(arrow_style) dash_style['stroke'] = self.color_marker_chords dash_style['stroke-dasharray'] = '4, 2, 1, 2' line = self.drawDimension((ptA[0]*unitFactor, ptA[1]*unitFactor), (ptD[0]*unitFactor, ptD[1]*unitFactor), dash_style, parent) line = self.drawDimension((ptB[0]*unitFactor, ptB[1]*unitFactor), (ptC[0]*unitFactor, ptC[1]*unitFactor), dash_style, parent) # chord labels centerx = ptB[0]*unitFactor + (ptC[0]-ptB[0])*unitFactor/2 centery = ptB[1]*unitFactor + (ptC[1]-ptB[1])*unitFactor/2 line_angle = calc_angle_between_points(ptC, ptB) ypos = centery+font_height+2 if line_angle<0 else centery-2 text_style['fill'] = self.color_marker_chords text_atts = {'style':simplestyle.formatStyle(text_style), 'transform': 'rotate(%f)' % (line_angle) } text = inkex.etree.SubElement(parent, 'text', text_atts) scale_matrix = [[1, 0.0, centerx], [0.0, 1, ypos]] # needs cos,sin corrections simpletransform.applyTransformToNode(scale_matrix, text) text.text = "%4.2f" % (chord_base) if cut_dia >= 0.001: centerx = ptA[0]*unitFactor + (ptD[0]-ptA[0])*unitFactor/2 centery = ptA[1]*unitFactor + (ptD[1]-ptA[1])*unitFactor/2 xpos = centerx - font_height*math.sin(math.radians(abs(line_angle))) ypos = centery-2 if line_angle>0 else centery+font_height+2 text = inkex.etree.SubElement(parent, 'text', text_atts) scale_matrix = [[1, 0.0, centerx], [0.0, 1, ypos]] simpletransform.applyTransformToNode(scale_matrix, text) text.text = "%4.2f" % (chord_cut) # frustum lines frustrum_repos = [[1, 0.0, 1], [0.0, 1, math.sqrt(pow(shortradius*unitFactor,2)-pow(cut_dia*unitFactor/2,2))]] text_style['fill'] = self.color_marker_base line_style['stroke'] = self.color_marker_base arrow_style['stroke'] = self.color_marker_base line_attribs = {'style': simplestyle.formatStyle(line_style), 'd': 'M %f,%f L %f,%f %f,%f %f,%f z' %(-cut_dia/2*unitFactor,0, cut_dia/2*unitFactor,0, base_dia/2*unitFactor,cone_height*unitFactor, -base_dia/2*unitFactor,cone_height*unitFactor)} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) simpletransform.applyTransformToNode(frustrum_repos, line) # ticks line_attribs = {'style': simplestyle.formatStyle(line_style), 'd': 'M %f,%f L %f,%f' %(-(5+cut_dia/2*unitFactor),0, -(5+base_dia/2*unitFactor),0 )} line = inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs) simpletransform.applyTransformToNode(frustrum_repos, line) # line = self.drawDimension((-base_dia/2*unitFactor,0), (-base_dia/2*unitFactor,cone_height*unitFactor), arrow_style, parent) simpletransform.applyTransformToNode(frustrum_repos, line) # frustum text text_atts = {'style':simplestyle.formatStyle(text_style), 'x': str(-(18+base_dia/2*unitFactor)), 'y': str(cone_height*unitFactor/2) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" %(cone_height) simpletransform.applyTransformToNode(frustrum_repos, text) if cut_dia >= 0.001: text_atts = {'style':simplestyle.formatStyle(text_style), 'x': '0', 'y': str(font_height) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" %(cut_dia) simpletransform.applyTransformToNode(frustrum_repos, text) text_atts = {'style':simplestyle.formatStyle(text_style), 'x': '0', 'y': str(cone_height*unitFactor+font_height) } text = inkex.etree.SubElement(parent, 'text', text_atts) text.text = "%4.3f" %(base_dia) simpletransform.applyTransformToNode(frustrum_repos, text)
def effect(self): if len(self.options.ids) != 2: inkex.errormsg(_("This extension requires two selected objects. The first selected object must be the straight line with two nodes.")) exit() # drawing that will be scaled is selected second, must be a single object scalepath = self.selected[self.options.ids[0]] drawing = self.selected[self.options.ids[1]] if scalepath.tag != inkex.addNS('path','svg'): inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead.")) exit() # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length simpletransform.fuseTransform(scalepath) path = cubicsuperpath.parsePath(scalepath.get('d')) if len(path) < 1 or len(path[0]) < 2: inkex.errormsg(_("This extension requires that the first selected path be two nodes long.")) exit() # calculate path length p1_x = path[0][0][1][0] p1_y = path[0][0][1][1] p2_x = path[0][1][1][0] p2_y = path[0][1][1][1] p_length = self.getUnittouu(str(distance((p1_x, p1_y),(p2_x, p2_y))) + self.getDocumentUnit()) # Find Drawing Scale if self.options.choosescale == 'metric': drawing_scale = int(self.options.metric) elif self.options.choosescale == 'imperial': drawing_scale = int(self.options.imperial) elif self.options.choosescale == 'custom': drawing_scale = int(self.options.custom_scale) # calculate scaling center center = self.calc_scale_center(p1_x, p1_y, p2_x, p2_y) # calculate scaling factor target_length = self.getUnittouu(str(self.options.length) + self.options.unit) factor = (target_length / p_length) / drawing_scale # inkex.debug("%s, %s %s" % (target_length, p_length, factor)) # Add scale ruler if self.options.showscale == "true": dist = int(self.options.unitlength) ruler_length = self.getUnittouu(str(dist) + self.options.unit) / drawing_scale ruler_pos = (p1_x + (p2_x - p1_x)/2, (p1_y + (p2_y - p1_y)/2) - self.getUnittouu('4 mm')) # TODO: add into current layer instead self.create_ruler(self.document.getroot(), ruler_length, ruler_pos, dist, drawing_scale) # Get drawing and current transformations for obj in (scalepath, drawing): # Scale both objects about the center, first translate back to origin scale_matrix = [[1, 0.0, -center[0]], [0.0, 1, -center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then scale scale_matrix = [[factor, 0.0, 0.0], [0.0, factor, 0.0]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then translate back to original scale center location scale_matrix = [[1, 0.0, center[0]], [0.0, 1, center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj)
def effect(self): #{{{ Check that elements have been selected if len(self.options.ids) == 0: inkex.errormsg(_("Please select objects!")) return #}}} #{{{ Drawing styles linestyle = { 'stroke' : '#000000', 'stroke-width' : str(self.unittouu('1px')), 'fill' : 'none' } facestyle = { 'stroke' : '#ff0000', 'stroke-width' : str(self.unittouu('1px')), 'fill' : 'none' } #}}} #{{{ Handle the transformation of the current group parentGroup = self.getParentNode(self.selected[self.options.ids[0]]) trans = self.getGlobalTransform(parentGroup) invtrans = None if trans: invtrans = simpletransform.invertTransform(trans) #}}} #{{{ Recovery of the selected objects pts = [] nodes = [] seeds = [] for id in self.options.ids: node = self.selected[id] nodes.append(node) bbox = simpletransform.computeBBox([node]) if bbox: cx = 0.5*(bbox[0]+bbox[1]) cy = 0.5*(bbox[2]+bbox[3]) pt = [cx,cy] if trans: simpletransform.applyTransformToPoint(trans,pt) pts.append(Point(pt[0],pt[1])) seeds.append(Point(cx,cy)) #}}} #{{{ Creation of groups to store the result if self.options.diagramType != 'Delaunay': # Voronoi groupVoronoi = inkex.etree.SubElement(parentGroup,inkex.addNS('g','svg')) groupVoronoi.set(inkex.addNS('label', 'inkscape'), 'Voronoi') if invtrans: simpletransform.applyTransformToNode(invtrans,groupVoronoi) if self.options.diagramType != 'Voronoi': # Delaunay groupDelaunay = inkex.etree.SubElement(parentGroup,inkex.addNS('g','svg')) groupDelaunay.set(inkex.addNS('label', 'inkscape'), 'Delaunay') #}}} #{{{ Clipping box handling if self.options.diagramType != 'Delaunay': #Clipping bounding box creation gBbox = simpletransform.computeBBox(nodes) #Clipbox is the box to which the Voronoi diagram is restricted clipBox = () if self.options.clipBox == 'Page': svg = self.document.getroot() w = self.unittouu(svg.get('width')) h = self.unittouu(svg.get('height')) clipBox = (0,w,0,h) else: clipBox = (2*gBbox[0]-gBbox[1], 2*gBbox[1]-gBbox[0], 2*gBbox[2]-gBbox[3], 2*gBbox[3]-gBbox[2]) #Safebox adds points so that no Voronoi edge in clipBox is infinite safeBox = (2*clipBox[0]-clipBox[1], 2*clipBox[1]-clipBox[0], 2*clipBox[2]-clipBox[3], 2*clipBox[3]-clipBox[2]) pts.append(Point(safeBox[0],safeBox[2])) pts.append(Point(safeBox[1],safeBox[2])) pts.append(Point(safeBox[1],safeBox[3])) pts.append(Point(safeBox[0],safeBox[3])) if self.options.showClipBox: #Add the clip box to the drawing rect = inkex.etree.SubElement(groupVoronoi,inkex.addNS('rect','svg')) rect.set('x',str(clipBox[0])) rect.set('y',str(clipBox[2])) rect.set('width',str(clipBox[1]-clipBox[0])) rect.set('height',str(clipBox[3]-clipBox[2])) rect.set('style',simplestyle.formatStyle(linestyle)) #}}} #{{{ Voronoi diagram generation if self.options.diagramType != 'Delaunay': vertices,lines,edges = voronoi.computeVoronoiDiagram(pts) for edge in edges: line = edge[0] vindex1 = edge[1] vindex2 = edge[2] if (vindex1 <0) or (vindex2 <0): continue # infinite lines have no need to be handled in the clipped box else: segment = self.clipEdge(vertices,lines,edge,clipBox) #segment = [vertices[vindex1],vertices[vindex2]] # deactivate clipping if len(segment)>1: v1 = segment[0] v2 = segment[1] cmds = [['M',[v1[0],v1[1]]],['L',[v2[0],v2[1]]]] path = inkex.etree.Element(inkex.addNS('path','svg')) path.set('d',simplepath.formatPath(cmds)) path.set('style',simplestyle.formatStyle(linestyle)) groupVoronoi.append(path) if self.options.diagramType != 'Voronoi': triangles = voronoi.computeDelaunayTriangulation(seeds) for triangle in triangles: p1 = seeds[triangle[0]] p2 = seeds[triangle[1]] p3 = seeds[triangle[2]] cmds = [['M',[p1.x,p1.y]], ['L',[p2.x,p2.y]], ['L',[p3.x,p3.y]], ['Z',[]]] path = inkex.etree.Element(inkex.addNS('path','svg')) path.set('d',simplepath.formatPath(cmds)) path.set('style',simplestyle.formatStyle(facestyle)) groupDelaunay.append(path)
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 drawGrid(self, x_center, y_center, doc_w, doc_h, pos_x=0, pos_y=0): if self.options.coords == "rotate": rot = " rotate(270)" else: rot = "" x_center -= pos_x y_center -= pos_y uufactor = self.getDocScale() uu_spacing = self.options.spacing / self.options.scale * 1000.0 * uufactor x_start = x_center - math.floor(x_center / uu_spacing) * uu_spacing y_start = y_center - math.floor(y_center / uu_spacing) * uu_spacing num_x = int(math.ceil(doc_w / uu_spacing)) num_y = int(math.ceil(doc_h / uu_spacing)) layer = self.currentLayer() g = inkex.etree.SubElement(layer, 'g') # Invert any sub-transforms of layer simpletransform.applyTransformToNode( SpeleoTransform.invertTransform( SpeleoTransform.getTotalTransform(g)), g) # Add translation simpletransform.applyTransformToNode( simpletransform.parseTransform("translate(%.6f, %.6f)" % (pos_x, pos_y)), g) if self.options.coords != "none": g.set( 'style', 'stroke:#888;fill:#888;stroke-width:' + str(uufactor * 0.2) + 'px;font-size:' + str(self.options.fontsize * uufactor * 0.352778) + 'px;text-anchor:end;text-align:end') cg = inkex.etree.SubElement(g, "g") g = inkex.etree.SubElement(g, "g") g.set('style', 'fill:none;') cg.set('style', 'stroke:none;stroke-width:0') else: g.set('style', 'stroke:#888;fill:none;stroke-width:' + str(uufactor * 0.2)) # Vertical lines and coordinates for x in range(0, num_x): x = x_start + x * uu_spacing if x > doc_w: break if self.options.type == "line": l = inkex.etree.SubElement(g, 'path') l.set('d', 'M ' + str(x) + ",0 L " + str(x) + "," + str(doc_h)) if self.options.coords != "none": l = inkex.etree.SubElement(cg, 'text') l.text = str( int( round((x - x_center) / uu_spacing * self.options.spacing) + self.options.origin_x)) + self.options.units l.set("style", "text-anchor:end;text-align:end") l.set("transform", ("translate(%.2f,%.2f)" + rot) % (x - 1.4 * uufactor, 4.2 * uufactor)) # Horizontal lines and coordinates for y in range(0, num_y): y = y_start + y * uu_spacing if y > doc_h: break if self.options.type == "line": l = inkex.etree.SubElement(g, 'path') l.set('d', 'M 0,' + str(y) + " L " + str(doc_w) + "," + str(y)) if self.options.coords != "none": l = inkex.etree.SubElement(cg, 'text') l.text = str( int(-round( (y - y_center) / uu_spacing * self.options.spacing) + self.options.origin_y)) + self.options.units l.set("style", "text-anchor:end;text-align:end") l.set( "transform", "translate(%.2f,%.2f)" % (12.7 * uufactor, y - 1.4 * uufactor)) # Crosses, if requested if self.options.type == "cross": l = inkex.etree.SubElement(g, 'path') path_id = self.uniqueId("gridCross", True) l.set('d', "M -10,0 10,0 M 0,-10 0,10") l.set("transform", "translate(%.2f, %.2f)" % (x_center, y_center)) l.set("id", path_id) for x in range(0, num_x): x_doc = x_start + x * uu_spacing - x_center if x_doc > doc_w: break for y in range(0, num_y): if x == 0 and y == 0: continue y_doc = y_start + y * uu_spacing - y_center if y_doc > doc_h: break l = inkex.etree.SubElement(g, 'use') l.set(inkex.addNS('href', 'xlink'), '#' + str(path_id)) l.set("transform", "translate(%.2f,%.2f)" % (x_doc, y_doc))
def moveNode(self, x, y, node, layer): transformation = 'translate(' + str(x) + ', ' + str(y) + ')' transform = simpletransform.parseTransform(transformation) simpletransform.applyTransformToNode(transform, node) layer.append(node)
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 objects. The first selected object must be the straight line with two nodes.")) exit() # drawing that will be scaled is selected second, must be a single object scalepath = self.selected[self.options.ids[0]] drawing = self.selected[self.options.ids[1]] if scalepath.tag != inkex.addNS('path','svg'): inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead.")) exit() # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length simpletransform.fuseTransform(scalepath) path = cubicsuperpath.parsePath(scalepath.get('d')) if len(path) < 1 or len(path[0]) < 2: inkex.errormsg(_("This extension requires that the first selected path be two nodes long.")) exit() # calculate path length p1_x = path[0][0][1][0] p1_y = path[0][0][1][1] p2_x = path[0][1][1][0] p2_y = path[0][1][1][1] p_length = self.getUnittouu(str(distance((p1_x, p1_y),(p2_x, p2_y))) + self.getDocumentUnit()) # Find Drawing Scale if self.options.choosescale == 'metric': drawing_scale = int(self.options.metric) elif self.options.choosescale == 'imperial': drawing_scale = int(self.options.imperial) elif self.options.choosescale == 'custom': drawing_scale = self.options.custom_scale # calculate scaling center center = self.calc_scale_center(p1_x, p1_y, p2_x, p2_y) # calculate scaling factor target_length = self.getUnittouu(str(self.options.length) + self.options.unit) factor = (target_length / p_length) / drawing_scale # inkex.debug("%s, %s %s" % (target_length, p_length, factor)) # Add scale ruler if self.options.showscale == "true": dist = int(self.options.unitlength) ruler_length = self.getUnittouu(str(dist) + self.options.unit) / drawing_scale ruler_pos = (p1_x + (p2_x - p1_x)/2, (p1_y + (p2_y - p1_y)/2) - self.getUnittouu('4 mm')) # TODO: add into current layer instead self.create_ruler(self.document.getroot(), ruler_length, ruler_pos, dist, drawing_scale) # Get drawing and current transformations for obj in (scalepath, drawing): # Scale both objects about the center, first translate back to origin scale_matrix = [[1, 0.0, -center[0]], [0.0, 1, -center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then scale scale_matrix = [[factor, 0.0, 0.0], [0.0, factor, 0.0]] simpletransform.applyTransformToNode(scale_matrix, obj) # Then translate back to original scale center location scale_matrix = [[1, 0.0, center[0]], [0.0, 1, center[1]]] simpletransform.applyTransformToNode(scale_matrix, obj)