示例#1
0
def layoutstring( imagelist, zoom ):					 # layout string of letter-images using optical kerning
	kernlist  = []
	length = zoom
	for entry in imagelist:
		if (entry == " "):							   # leaving room for " " space characters
			length = length + (zoom * render_alphabetsoup_config.space)
		else:
			image, width, height = entry
			length = length + width + zoom   # add letter length to overall length
			kernlist.append( optikern(image, width, zoom) )		   # append kerning data for this image 

	workspace = None

	position = zoom
	for i in range(0, len(kernlist)):
		while(imagelist[i] == " "):
			position = position + (zoom * render_alphabetsoup_config.space )
			imagelist.pop(i)
		image, width, height = imagelist[i]

		# set the kerning
		if i == 0: kern = 0						  # for first image, kerning is zero
		else:
			kerncompare = []							 # kerning comparison array
			for j in range( 0, len(kernlist[i][0])):
				kerncompare.append( kernlist[i][0][j]+kernlist[i-1][1][j] )
			kern = min( kerncompare )

		position = position - kern					   # move position back by kern amount
		thisimage = copy.deepcopy(image)		
		simplepath.translatePath(thisimage, position, 0)
		workspace = combinePaths(workspace, thisimage)
		position = position + width + zoom	# advance position by letter width

	return workspace
示例#2
0
    def test_simplepath(self):
        """Test simplepath API"""
        import simplepath

        data = 'M12 34L56 78Z'
        path = simplepath.parsePath(data)
        self.assertEqual(path,
                         [['M', [12., 34.]], ['L', [56., 78.]], ['Z', []]])

        d_out = simplepath.formatPath(path)
        d_out = d_out.replace('.0', '')
        self.assertEqual(data.replace(' ', ''), d_out.replace(' ', ''))

        simplepath.translatePath(path, -3, -4)
        self.assertEqual(path,
                         [['M', [9., 30.]], ['L', [53., 74.]], ['Z', []]])

        simplepath.scalePath(path, 10, 20)
        self.assertEqual(path,
                         [['M', [90., 600.]], ['L', [530., 1480.]], ['Z', []]])

        simplepath.rotatePath(path, math.pi / 2.0, cx=5, cy=7)
        approxed = [[code, approx(coords)] for (code, coords) in path]
        self.assertEqual(
            approxed, [['M', [-588., 92.]], ['L', [-1468., 532.]], ['Z', []]])
示例#3
0
def inkscape(hpgl, svg, inkex):
    layer = inkex.etree.SubElement(svg, 'g')
    layer.set(inkex.addNS('label', 'inkscape'), 'InkCut Preview Layer')
    layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
    spPU = [['M', [0, 0]]]
    spPD = []
    for c in hpgl.split(';'):
        if c[:2] == "PU":
            p = map(int, c[2:].split(','))
            spPD.append(['M', p])
            spPU.append(['L', p])
        elif c[:2] == "PD":
            p = map(int, c[2:].split(','))
            spPU.append(['M', p])
            spPD.append(['L', p])

    pu = inkex.etree.Element(inkex.addNS('path', 'svg'))

    simplepath.scalePath(spPU, 0.088582677, -0.088582677)
    simplepath.translatePath(spPU, 0, float(svg.get('height')))

    style = {'fill': 'none', 'stroke-opacity': '.8', 'stroke': '#116AAB'}
    pu.set('style', simplestyle.formatStyle(style))
    pu.set('d', simplepath.formatPath(spPU))

    pd = inkex.etree.Element(inkex.addNS('path', 'svg'))

    style = {'fill': 'none', 'stroke-opacity': '.8', 'stroke': '#AB3011'}
    pd.set('style', simplestyle.formatStyle(style))
    pd.set('d', simplepath.formatPath(spPD))

    # Connect elements together.
    layer.append(pu)
    layer.append(pd)
    def effect(self):
        #References:   Minimum Requirements for Creating a DXF File of a 3D Model By Paul Bourke
        #              NURB Curves: A Guide for the Uninitiated By Philip J. Schneider
        #              The NURBS Book By Les Piegl and Wayne Tiller (Springer, 1995)
        self.dxf_add("999\nDXF created by Inkscape\n")
        self.dxf_add(dxf_templates.r14_header)

        scale = 25.4/90.0
        h = inkex.unittouu(self.document.getroot().xpath('@height', namespaces=inkex.NSS)[0])
        path = '//svg:path'
        for node in self.document.getroot().xpath(path, namespaces=inkex.NSS):
            d = node.get('d')
            sim = simplepath.parsePath(d)
            if len(sim):
                simplepath.scalePath(sim,scale,-scale)
                simplepath.translatePath(sim,0,h*scale)            
                p = cubicsuperpath.CubicSuperPath(sim)
                for sub in p:
                    for i in range(len(sub)-1):
                        s = sub[i]
                        e = sub[i+1]
                        if s[1] == s[2] and e[0] == e[1]:
                            self.dxf_line([s[1],e[1]])
                        elif (self.options.ROBO == 'true'):
                            self.ROBO_spline([s[1],s[2],e[0],e[1]])
                        else:
                            self.dxf_spline([s[1],s[2],e[0],e[1]])
        if self.options.ROBO == 'true':
            self.ROBO_output()
        self.LWPOLY_output()
        self.dxf_add(dxf_templates.r14_footer)
示例#5
0
def inkscape(hpgl,svg,inkex):
	layer = inkex.etree.SubElement(svg, 'g')
	layer.set(inkex.addNS('label', 'inkscape'), 'InkCut Preview Layer')
	layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
	spPU = [['M',[0,0]]]
	spPD = []
	for c in hpgl.split(';'):
		if c[:2] == "PU":
			p = map(int,c[2:].split(','))
			spPD.append(['M',p])
			spPU.append(['L',p])
		elif c[:2] == "PD":
			p = map(int,c[2:].split(','))
			spPU.append(['M',p])
			spPD.append(['L',p])		
	
	pu = inkex.etree.Element(inkex.addNS('path','svg'))
	
	simplepath.scalePath(spPU,0.088582677,-0.088582677)
	simplepath.translatePath(spPU,0,float(svg.get('height')))
	
	style = {'fill' : 'none','stroke-opacity': '.8','stroke':'#116AAB'}
	pu.set('style', simplestyle.formatStyle(style))
	pu.set('d',simplepath.formatPath(spPU))
	
	
	pd = inkex.etree.Element(inkex.addNS('path','svg'))
	
	style = {'fill' : 'none','stroke-opacity': '.8','stroke':'#AB3011'}
	pd.set('style', simplestyle.formatStyle(style))
	pd.set('d',simplepath.formatPath(spPD))
	
	# Connect elements together.
	layer.append(pu)
	layer.append(pd)
示例#6
0
def realistic_stitch(start, end):
    """Generate a stitch vector path given a start and end point."""

    end = Point(*end)
    start = Point(*start)

    stitch_length = (end - start).length()
    stitch_center = (end + start) / 2.0
    stitch_direction = (end - start)
    stitch_angle = math.atan2(stitch_direction.y, stitch_direction.x)

    stitch_length = max(0, stitch_length - 0.2 * PIXELS_PER_MM)

    # create the path by filling in the length in the template
    path = simplepath.parsePath(stitch_path % stitch_length)

    # rotate the path to match the stitch
    rotation_center_x = -stitch_length / 2.0
    rotation_center_y = stitch_height / 2.0
    simplepath.rotatePath(path,
                          stitch_angle,
                          cx=rotation_center_x,
                          cy=rotation_center_y)

    # move the path to the location of the stitch
    simplepath.translatePath(path, stitch_center.x - rotation_center_x,
                             stitch_center.y - rotation_center_y)

    return simplepath.formatPath(path)
def getTranslatedPath(d, posX, posY):
    if(CommonDefs.inkVer == 1.0):
        path = Path(d)
        path.translate(posX, posY, inplace = True)
        return path.to_superpath().__str__()
    else:
        path = simplepath.parsePath(d)
        simplepath.translatePath(path, posX, posY)
        return simplepath.formatPath(path)
示例#8
0
    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)
示例#9
0
    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)
示例#10
0
def hpgl(plot):
    #create a preview svg
    svg = etree.Element(inkex.addNS('svg', 'svg'))
    svg.set('height', str(plot.dimensions[1]))
    svg.set(
        'width',
        str(plot.getSize()[0] + plot.startPosition[0] +
            plot.finishPosition[0]))
    svg.set('version', '1.1')
    """
	bg = inkex.etree.Element(inkex.addNS('rect','svg'))
	style = {'fill' : 'none','stroke-opacity': '.8','stroke':'#212425','stroke-width':'10'}
	bg.set('style', simplestyle.formatStyle(style))
	bg.set('x','0')
	bg.set('y','0')
	bg.set('width',str(plot.dimensions[0]))
	bg.set('height',svg.get('height'))
	svg.append(bg)
	"""
    spPU = [['M', [0, 0]]]
    spPD = []
    for c in plot.toHPGL().split(';'):
        if c[:2] == "PU":
            p = map(int, c[2:].split(','))
            spPD.append(['M', p])
            spPU.append(['L', p])
        elif c[:2] == "PD":
            p = map(int, c[2:].split(','))
            spPU.append(['M', p])
            spPD.append(['L', p])

    pu = inkex.etree.Element(inkex.addNS('path', 'svg'))

    simplepath.scalePath(spPU, 0.088582677, -0.088582677)
    simplepath.translatePath(spPU, 0, float(svg.get('height')))

    style = {'fill': 'none', 'stroke-opacity': '.8', 'stroke': '#116AAB'}
    pu.set('style', simplestyle.formatStyle(style))
    pu.set('d', simplepath.formatPath(spPU))

    pd = inkex.etree.Element(inkex.addNS('path', 'svg'))

    style = {'fill': 'none', 'stroke-opacity': '.8', 'stroke': '#AB3011'}
    pd.set('style', simplestyle.formatStyle(style))
    pd.set('d', simplepath.formatPath(spPD))

    # Connect elements together.
    svg.append(pu)
    svg.append(pd)
    return svg
示例#11
0
def hpgl(plot):
	#create a preview svg
	svg = etree.Element(inkex.addNS('svg','svg'))
	svg.set('height',str(plot.dimensions[1]))
	svg.set('width',str(plot.getSize()[0]+plot.startPosition[0]+plot.finishPosition[0]))
	svg.set('version','1.1')
	"""
	bg = inkex.etree.Element(inkex.addNS('rect','svg'))
	style = {'fill' : 'none','stroke-opacity': '.8','stroke':'#212425','stroke-width':'10'}
	bg.set('style', simplestyle.formatStyle(style))
	bg.set('x','0')
	bg.set('y','0')
	bg.set('width',str(plot.dimensions[0]))
	bg.set('height',svg.get('height'))
	svg.append(bg)
	"""
	spPU = [['M',[0,0]]]
	spPD = []
	for c in plot.toHPGL().split(';'):
		if c[:2] == "PU":
			p = map(int,c[2:].split(','))
			spPD.append(['M',p])
			spPU.append(['L',p])
		elif c[:2] == "PD":
			p = map(int,c[2:].split(','))
			spPU.append(['M',p])
			spPD.append(['L',p])		
	
	pu = inkex.etree.Element(inkex.addNS('path','svg'))
	
	simplepath.scalePath(spPU,0.088582677,-0.088582677)
	simplepath.translatePath(spPU,0,float(svg.get('height')))
	
	style = {'fill' : 'none','stroke-opacity': '.8','stroke':'#116AAB'}
	pu.set('style', simplestyle.formatStyle(style))
	pu.set('d',simplepath.formatPath(spPU))
	
	
	pd = inkex.etree.Element(inkex.addNS('path','svg'))
	
	style = {'fill' : 'none','stroke-opacity': '.8','stroke':'#AB3011'}
	pd.set('style', simplestyle.formatStyle(style))
	pd.set('d',simplepath.formatPath(spPD))
	
	# Connect elements together.
	svg.append(pu)
	svg.append(pd)
	return svg
示例#12
0
    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
示例#13
0
    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(stack):  # draw a character based on a tree stack
    state = stack.pop(0)
    #print state,

    image, width, height = loadPath(font + syntax[state][0])  # load the image
    if (stack[0] != "["):  # terminal stack element
        if (len(syntax[state]) == 1):  # this state is a terminal node
            return image, width, height
        else:
            substack = generate(state)  # generate random substack
            return draw(substack)  # draw random substack
    else:
        #inkex.debug("[")
        stack.pop(0)
        images = []  # list of daughter images
        nodes = []  # list of daughter names
        while (stack[0] != "]"):  # for all nodes in stack
            newstate = stack[0]  # the new state
            newimage, width, height = draw(stack)  # draw the daughter state
            if (newimage):
                tfimage = mxfm(newimage, width, height,
                               stack)  # maybe transform daughter state
                images.append([tfimage, width,
                               height])  # list of daughter images
                nodes.append(newstate)  # list of daughter nodes
            else:
                #inkex.debug(("recurse on",newstate,"failed")) # this should never happen
                return None, 0, 0
        rule = findrule(state, nodes)  # find the rule for this subtree

        for i in range(0, len(images)):
            currimg, width, height = images[i]

            if currimg:
                #box = getPathBoundingBox(currimg)
                dx = rule[i][1] * units
                dy = rule[i][2] * units
                #newbox = ((box[0]+dx),(box[1]+dy),(box[2]+dx),(box[3]+dy))
                simplepath.translatePath(currimg, dx, dy)
                image = combinePaths(image, currimg)

        stack.pop(0)
        return image, width, height
示例#15
0
def draw(stack):  # draw a character based on a tree stack
    state = stack.pop(0)
    # print state,

    image, width, height = loadPath(font + syntax[state][0])  # load the image
    if stack[0] != "[":  # terminal stack element
        if len(syntax[state]) == 1:  # this state is a terminal node
            return image, width, height
        else:
            substack = generate(state)  # generate random substack
            return draw(substack)  # draw random substack
    else:
        # inkex.debug("[")
        stack.pop(0)
        images = []  # list of daughter images
        nodes = []  # list of daughter names
        while stack[0] != "]":  # for all nodes in stack
            newstate = stack[0]  # the new state
            newimage, width, height = draw(stack)  # draw the daughter state
            if newimage:
                tfimage = mxfm(newimage, width, height, stack)  # maybe transform daughter state
                images.append([tfimage, width, height])  # list of daughter images
                nodes.append(newstate)  # list of daughter nodes
            else:
                # inkex.debug(("recurse on",newstate,"failed")) # this should never happen
                return None, 0, 0
        rule = findrule(state, nodes)  # find the rule for this subtree

        for i in range(0, len(images)):
            currimg, width, height = images[i]

            if currimg:
                # box = getPathBoundingBox(currimg)
                dx = rule[i][1] * units
                dy = rule[i][2] * units
                # newbox = ((box[0]+dx),(box[1]+dy),(box[2]+dx),(box[3]+dy))
                simplepath.translatePath(currimg, dx, dy)
                image = combinePaths(image, currimg)

        stack.pop(0)
        return image, width, height
def resolve_path(node, transform=False):
    path = simplepath.parsePath(node.attrib['d'])
    if transform and 'transform' in node.attrib:
        transforms = re.findall(
            "([a-z,A-Z]+)\(([0-9,\s,.,-]*)\)",
            node.attrib['transform'])
        for k, vs in transforms:
            sc = ' '
            if ',' in vs:
                sc = ','
            args = map(lambda v: float(v.strip()), vs.split(sc))
            if k == 'translate':
                simplepath.translatePath(path, *args)
            elif k == 'scale':
                simplepath.scalePath(path, *args)
            elif k == 'rotate':
                simplepath.rotatePath(path, *args)
            else:
                error(
                    "Invalid path data: contains unsupported transform %s" % k)
    return path
示例#17
0
    def effect(self):
        #References:   Minimum Requirements for Creating a DXF File of a 3D Model By Paul Bourke
        #              NURB Curves: A Guide for the Uninitiated By Philip J. Schneider
        self.dxf_add("999\nDXF created by Inkscape\n0\nSECTION\n2\nENTITIES")
        
        scale = 25.4/90.0
        h = inkex.unittouu(inkex.xml.xpath.Evaluate('/svg/@height',self.document)[0].value)

        path = '//path'
        for node in inkex.xml.xpath.Evaluate(path,self.document):
            d = node.attributes.getNamedItem('d').value
            sim = simplepath.parsePath(d)
            simplepath.scalePath(sim,scale,-scale)
            simplepath.translatePath(sim,0,h*scale)            
            p = cubicsuperpath.CubicSuperPath(sim)
            for sub in p:
                for i in range(len(sub)-1):
                    s = sub[i]
                    e = sub[i+1]
                    if s[1] == s[2] and e[0] == e[1]:
                        self.dxf_line([s[1],e[1]])
                    else:
                        self.dxf_spline([s[1],s[2],e[0],e[1]])
        self.dxf_add("\n0\nENDSEC\n0\nEOF\n")
def draw_crop_scale(stack, zoom):  # draw, crop and scale letter image
    image, width, height = draw(stack)
    bbox = getPathBoundingBox(image)
    simplepath.translatePath(image, -bbox[0], 0)
    simplepath.scalePath(image, zoom / units, zoom / units)
    return image, bbox[1] - bbox[0], bbox[3] - bbox[2]
示例#19
0
	def translatePath(self,x,y):
		simplepath.translatePath(self.data,x,y)
示例#20
0
def draw_crop_scale(stack, zoom):  # draw, crop and scale letter image
    image, width, height = draw(stack)
    bbox = getPathBoundingBox(image)
    simplepath.translatePath(image, -bbox[0], 0)
    simplepath.scalePath(image, zoom / units, zoom / units)
    return image, bbox[1] - bbox[0], bbox[3] - bbox[2]
示例#21
0
	def flip_cordinate_system(self, d, emsize, baseline):
		pathdata = simplepath.parsePath(d)
		simplepath.scalePath(pathdata, 1,-1)
		simplepath.translatePath(pathdata, 0, int(emsize) - int(baseline))
		return simplepath.formatPath(pathdata)
示例#22
0
 def flip_cordinate_system(self, d, emsize, baseline):
     pathdata = simplepath.parsePath(d)
     simplepath.scalePath(pathdata, 1, -1)
     simplepath.translatePath(pathdata, 0, int(emsize) - int(baseline))
     return simplepath.formatPath(pathdata)
示例#23
0
    def effect(self):

        # get user-entered params
        x_scale = self.options.x_scale
        y_scale = self.options.y_scale

        t_start = self.options.t_start
        t_end = self.options.t_end
        n_steps = self.options.n_steps
        fps = self.options.fps
        dt = self.options.dt

        x_eqn = self.options.x_eqn
        y_eqn = self.options.y_eqn

        x_size_eqn = self.options.x_size_eqn
        y_size_eqn = self.options.y_size_eqn

        theta_eqn = self.options.theta_eqn

        # get doc root
        svg = self.document.getroot()
        doc_w = self.unittouu(svg.get('width'))
        doc_h = self.unittouu(svg.get('height'))

        # get selected items and validate
        selected = pathmodifier.zSort(self.document.getroot(),
                                      self.selected.keys())

        if not selected:
            inkex.errormsg(
                'Exactly two objects must be selected: a rect and a template. See "help" for details.'
            )
            return
        elif len(selected) != 2:
            inkex.errormsg(
                'Exactly two objects must be selected: a rect and a template. See "help" for details.'
            )
            return

        # rect
        rect = self.selected[selected[0]]

        if not rect.tag.endswith('rect'):
            inkex.errormsg('Bottom object must be rect. See "help" for usage.')
            return

        # object
        obj = self.selected[selected[1]]

        if not (obj.tag.endswith('path') or obj.tag.endswith('g')):
            inkex.errormsg(
                'Template object must be path or group of paths. See "help" for usage.'
            )
            return
        if obj.tag.endswith('g'):
            children = obj.getchildren()
            if not all([ch.tag.endswith('path') for ch in children]):
                msg = 'All elements of group must be paths, but they are: '
                msg += ', '.join(['{}'.format(ch) for ch in children])
                inkex.errormsg(msg)
                return
            objs = children
            is_group = True
        else:
            objs = [obj]
            is_group = False

        # get rect params
        w = float(rect.get('width'))
        h = float(rect.get('height'))

        x_rect = float(rect.get('x'))
        y_rect = float(rect.get('y'))

        # lower left corner
        x_0 = x_rect
        y_0 = y_rect + h

        # get object path(s)
        obj_ps = [simplepath.parsePath(obj_.get('d')) for obj_ in objs]
        n_segs = [len(obj_p_) for obj_p_ in obj_ps]
        obj_p = sum(obj_ps, [])

        # compute travel parameters
        if not n_steps:
            # compute dt
            if dt == 0:
                dt = 1. / fps
            ts = np.arange(t_start, t_end, dt)
        else:
            ts = np.linspace(t_start, t_end, n_steps)

        # compute xs, ys, stretches, and rotations in arbitrary coordinates
        xs = np.nan * np.zeros(len(ts))
        ys = np.nan * np.zeros(len(ts))
        x_sizes = np.nan * np.zeros(len(ts))
        y_sizes = np.nan * np.zeros(len(ts))
        thetas = np.nan * np.zeros(len(ts))

        for ctr, t in enumerate(ts):
            xs[ctr] = eval(x_eqn)
            ys[ctr] = eval(y_eqn)
            x_sizes[ctr] = eval(x_size_eqn)
            y_sizes[ctr] = eval(y_size_eqn)
            thetas[ctr] = eval(theta_eqn) * pi / 180

        # ensure no Infs
        if np.any(np.isinf(xs)):
            raise Exception('Inf detected in x(t), please remove.')
            return
        if np.any(np.isinf(ys)):
            raise Exception('Inf detected in y(t), please remove.')
            return
        if np.any(np.isinf(x_sizes)):
            raise Exception('Inf detected in x_size(t), please remove.')
            return
        if np.any(np.isinf(y_sizes)):
            raise Exception('Inf detected in y_size(t), please remove.')
            return
        if np.any(np.isinf(thetas)):
            raise Exception('Inf detected in theta(t), please remove.')
            return

        # convert to screen coordinates
        xs *= (w / x_scale)
        xs += x_0

        ys *= (-h / y_scale)  # neg sign to invert y for inkscape screen
        ys += y_0

        # get obj center
        b_box = simpletransform.refinedBBox(
            cubicsuperpath.CubicSuperPath(obj_p))
        c_x = 0.5 * (b_box[0] + b_box[1])
        c_y = 0.5 * (b_box[2] + b_box[3])

        # get rotation anchor
        if any([k.endswith('transform-center-x') for k in obj.keys()]):
            k_r_x = [
                k for k in obj.keys() if k.endswith('transform-center-x')
            ][0]
            k_r_y = [
                k for k in obj.keys() if k.endswith('transform-center-y')
            ][0]
            r_x = c_x + float(obj.get(k_r_x))
            r_y = c_y - float(obj.get(k_r_y))
        else:
            r_x, r_y = c_x, c_y

        paths = []

        # compute new paths
        for x, y, x_size, y_size, theta in zip(xs, ys, x_sizes, y_sizes,
                                               thetas):

            path = deepcopy(obj_p)

            # move to origin
            simplepath.translatePath(path, -x_0, -y_0)

            # move rotation anchor accordingly
            r_x_1 = r_x - x_0
            r_y_1 = r_y - y_0

            # scale
            simplepath.scalePath(path, x_size, y_size)

            # scale rotation anchor accordingly
            r_x_2 = r_x_1 * x_size
            r_y_2 = r_y_1 * y_size

            # move to final location
            simplepath.translatePath(path, x, y)

            # move rotation anchor accordingly
            r_x_3 = r_x_2 + x
            r_y_3 = r_y_2 + y

            # rotate
            simplepath.rotatePath(path, -theta, cx=r_x_3, cy=r_y_3)

            paths.append(path)

        parent = self.current_layer
        group = inkex.etree.SubElement(parent, inkex.addNS('g', 'svg'), {})

        for path in paths:

            if is_group:
                group_ = inkex.etree.SubElement(group, inkex.addNS('g', 'svg'),
                                                {})
                path_components = split(path, n_segs)

                for path_component, child in zip(path_components, children):
                    attribs = {k: child.get(k) for k in child.keys()}

                    attribs['d'] = simplepath.formatPath(path_component)

                    child_copy = inkex.etree.SubElement(
                        group_, child.tag, attribs)

            else:
                attribs = {k: obj.get(k) for k in obj.keys()}

                attribs['d'] = simplepath.formatPath(path)

                obj_copy = inkex.etree.SubElement(group, obj.tag, attribs)
示例#24
0
 def translatePath(self, x, y):
     simplepath.translatePath(self.data, x, y)