コード例 #1
0
ファイル: test_inkex_paths.py プロジェクト: wachin/inkscape
    def test_single_point_transform(self):
        from math import sqrt, sin, cos
        self.assertAlmostTuple(list(Path("M 10 10 30 20").control_points),
                               ((10, 10), (30, 20)))
        self.assertAlmostTuple(
            list(
                Path("M 10 10 30 20").transform(
                    Transform(translate=(10, 7))).control_points),
            ((20, 17), (40, 27)))
        self.assertAlmostTuple(
            list(
                Path("M 20 20 5 0 0 7 ").transform(
                    Transform(scale=10)).control_points),
            ((200, 200), (50, 0), (0, 70)))

        self.assertAlmostTuple(
            list(
                Path("M 20 20 1 0").transform(
                    Transform(rotate=90)).control_points), ((-20, 20), (0, 1)))

        self.assertAlmostTuple(
            list(
                Path("M 20 20 1 0").transform(
                    Transform(rotate=45)).control_points),
            ((0, sqrt(20**2 + 20**2)), (sqrt(2) / 2, sqrt(2) / 2)))

        self.assertAlmostTuple(
            list(
                Path("M 1 0 0 1").transform(
                    Transform(rotate=30)).control_points),
            ((sqrt(3) / 2, 0.5), (-0.5, sqrt(3) / 2)))
コード例 #2
0
 def test_interpolate(self):
     """Test interpolate with other transform"""
     t1 = Transform((0, 0, 0, 0, 0, 0))
     t2 = Transform((1, 1, 1, 1, 1, 1))
     val = t1.interpolate(t2, 0.5)
     assert all(
         getattr(val, a) == pytest.approx(0.5, 1e-3) for a in 'abcdef')
コード例 #3
0
 def test_scale(self):
     """In-place scaling from blank transform"""
     elem = self.svg.getElementById('F')
     self.assertEqual(elem.transform, Transform())
     self.assertEqual(elem.get('transform'), None)
     elem.transform.add_scale(1.0666666666666667, 1.0666666666666667)
     self.assertEqual(elem.get('transform'), Transform(scale=1.06667))
     self.assertIn(b'transform', etree.tostring(elem))
コード例 #4
0
    def exportDrill(self, kicad_mod=False):
        self.setInkscapeScaling()

        kicad_drill_string = ""

        i = 0

        if kicad_mod:
            pad_template = "(pad {n} thru_hole circle (at {x} {y}) (size {d} {d}) (drill {d}) (layers *.Cu *.Mask))\n"
        else:
            pad_template = """
                (module Wire_Pads:SolderWirePad_single_0-8mmDrill (layer F.Cu) (tedit 0) (tstamp 5ABD66D0)
                    (at {x} {y})
                    (pad {n} thru_hole circle (at 0 0) (size {d} {d}) (drill {d}) (layers *.Cu *.Mask))
                )
            """

        layerPath = '//svg:g[@inkscape:groupmode="layer"][@inkscape:label="Drill"]'

        for layer in self.document.getroot().xpath(layerPath,
                                                   namespaces=inkex.NSS):

            layer_trans = layer.get('transform')
            if layer_trans:
                layer_m = Transform(layer_trans).matrix
            else:
                layer_m = IDENTITY_MATRIX

            nodePath = 'descendant::svg:circle'

            count = 0
            for node in layer.xpath(nodePath, namespaces=inkex.NSS):
                count = count + 1
                cx = float(node.get('cx'))
                cy = float(node.get('cy'))

                radius = float(node.get('r'))
                drill_size = radius * 2

                t = node.get('transform')

                if t:
                    m = Transform(t).matrix
                    trans = (Transform(layer_m) * Transform(m)).matrix
                else:
                    trans = layer_m

                pt = Transform(trans).apply_to_point([cx, cy])
                padCoord = self.coordToKicad(pt)

                kicad_drill_string += pad_template.format(x=padCoord[0],
                                                          y=padCoord[1],
                                                          n=count,
                                                          d=drill_size)

        return kicad_drill_string
コード例 #5
0
    def test_pop_wrapped_attribute(self):
        """Remove wrapped attribute using .pop()"""
        group = Group()

        self.assertEqual(group.pop('transform'), Transform())

        group.update(
            transform=Transform(scale=2)
        )
        self.assertEqual(group.pop('transform'), Transform(scale=2))
        self.assertEqual(group.pop('transform'), Transform())
        self.assertRaises(AttributeError, getattr, group, 'foo')
コード例 #6
0
 def test_update_consistant(self):
     """Update doesn't keep callbacks around"""
     elem = self.svg.getElementById('D')
     tr_a = Transform(translate=(10, 10))
     tr_b = Transform(translate=(-20, 15))
     elem.transform = tr_a
     elem.transform = tr_b
     self.assertEqual(str(elem.transform), 'translate(-20, 15)')
     tr_a.add_translate(10, 10)
     self.assertEqual(str(elem.transform), 'translate(-20, 15)')
     elem.set('transform', None)
     self.assertEqual(elem.get('transform'), None)
コード例 #7
0
ファイル: test_inkex_paths.py プロジェクト: wachin/inkscape
    def test_inline_transformations(self):
        path = Path()
        self.assertTrue(path is not path.translate(10, 20))
        self.assertTrue(path is not path.transform(Transform(scale=10)))
        self.assertTrue(path is not path.rotate(10))
        self.assertTrue(path is not path.scale(10, 20))

        self.assertTrue(path is path.translate(10, 20, inplace=True))
        self.assertTrue(
            path is path.transform(Transform(scale=10), inplace=True))
        self.assertTrue(path is path.rotate(10, inplace=True))
        self.assertTrue(path is path.scale(10, 20, inplace=True))
コード例 #8
0
    def test_set_wrapped_attribute(self):
        """Remove wrapped attribute using .set()"""
        group = Group().update(
            transform=Transform(scale=2)
        )
        self.assertEqual(group.transform.matrix[0][0], 2)
        self.assertEqual(group.transform.matrix[1][1], 2)

        group.update(
            transform=None
        )
        self.assertEqual(group.transform, Transform())
コード例 #9
0
    def recursiveFuseTransform(self,
                               node,
                               transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):
        transf = Transform(transf) * Transform(node.get("transform", None))

        if 'transform' in node.attrib:
            del node.attrib['transform']

        node = ApplyTransform.objectToPath(node)

        if 'd' in node.attrib:
            d = node.get('d')
            p = CubicSuperPath(d)
            p = Path(p).to_absolute().transform(transf, True)
            node.set('d', Path(CubicSuperPath(p).to_path()))

            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS('polygon', 'svg'),
                inkex.addNS('polyline', 'svg')
        ]:
            points = node.get('points')
            points = points.strip().split(' ')
            for k, p in enumerate(points):
                if ',' in p:
                    p = p.split(',')
                    p = [float(p[0]), float(p[1])]
                    applyTransformToPoint(transf, p)
                    p = [str(p[0]), str(p[1])]
                    p = ','.join(p)
                    points[k] = p
            points = ' '.join(points)
            node.set('points', points)

            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS('rect', 'svg'),
                inkex.addNS('text', 'svg'),
                inkex.addNS('image', 'svg'),
                inkex.addNS('use', 'svg'),
                inkex.addNS('circle', 'svg')
        ]:
            # node.set('transform', str(Transform(transf)))
            inkex.utils.errormsg("Shape %s not yet supported" % node.tag)

        else:
            # e.g. <g style="...">
            self.scaleStrokeWidth(node, transf)

        for child in node.getchildren():
            self.recursiveFuseTransform(child, transf)
コード例 #10
0
 def test_in_place_transforms(self):
     """Do style and transforms update correctly"""
     elem = self.svg.getElementById('D')
     self.assertEqual(type(elem.transform), Transform)
     self.assertEqual(type(elem.style), Style)
     self.assertTrue(elem.transform)
     elem.transform = Transform()
     self.assertEqual(elem.transform, Transform())
     self.assertEqual(elem.get('transform'), None)
     self.assertNotIn(b'transform', etree.tostring(elem))
     elem.transform.add_translate(10, 10)
     self.assertIn(b'transform', etree.tostring(elem))
     elem.transform.add_translate(-10, -10)
     self.assertNotIn(b'transform', etree.tostring(elem))
コード例 #11
0
 def getGlobalTransform(self, node):
     parent = node.getparent()
     myTrans = Transform(node.get('transform')).matrix
     if myTrans:
         if parent is not None:
             parentTrans = self.getGlobalTransform(parent)
             if parentTrans:
                 return Transform(parentTrans) * Transform(myTrans)
             else:
                 return myTrans
     else:
         if parent is not None:
             return self.getGlobalTransform(parent)
         else:
             return None
コード例 #12
0
ファイル: test_inkex_paths.py プロジェクト: wachin/inkscape
 def test_arc_transformation(self):
     cases = [
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((1, 0, 1), (0, 1, 0)),
          "M 11 10 A 100 100 0 1 0 101 100 Z"),
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((1, 0, 0), (0, 1, 1)),
          "M 10 11 A 100 100 0 1 0 100 101 Z"),
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((1, 0, 1), (0, 1, 1)),
          "M 11 11 A 100 100 0 1 0 101 101 Z"),
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((2, 0, 0), (0, 1, 0)),
          "M 20 10 A 200 100 0 1 0 200 100 Z"),
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((1, 0, 0), (0, 2, 0)),
          "M 10 20 A 200 100 90 1 0 100 200 Z"),
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((1, 0, 0), (0, -1, 0)),
          "M 10 -10 A 100 100 0 1 1 100 -100 Z"),
         ("M 10 10 A 100 100 0 1 0 100 100 Z", ((1, 2, 0), (0, 2, 0)),
          "M 30 20 "
          "A 292.081 68.4742 41.4375 1 0 300 200 Z"),
         ("M 10 10 "
          "A 100 100 0 1 0 100 100 "
          "A 300 200 0 1 0 50 20 Z", ((1, 2, 0), (5, 6, 0)), "M 30,110 "
          "A 810.90492,49.327608 74.368134 1 1 "
          "300,1100 1981.2436,121.13604 75.800007 1 1 90,370 Z"),
     ]
     for path, transform, expected in cases:
         expected = Path(expected)
         result = Path(path).transform(Transform(matrix=transform))
         self.assertDeepAlmostEqual(expected.to_arrays(),
                                    result.to_arrays(),
                                    places=4)
コード例 #13
0
ファイル: simpletransform.py プロジェクト: wachin/inkscape
def applyTransformToPoint(mat, pt):
    """Transform(mat).apply_to_point(pt)"""
    pt2 = Transform(mat).apply_to_point(pt)
    # Apply in place as original method was modifying arrays in place.
    # but don't do this in your code! This is not good code design.
    pt[0] = pt2[0]
    pt[1] = pt2[1]
コード例 #14
0
ファイル: __init__.py プロジェクト: knifelees3/textext
        def _expand_defs(root):
            from inkex.transforms import Transform
            from inkex.elements import ShapeElement
            from copy import deepcopy
            for el in root:
                if isinstance(el, inkex.elements.Use):
                    # <group> element will replace <use> node
                    group = inkex.elements.Group()

                    # add all objects from symbol node
                    for obj in el.href:
                        group.append(deepcopy(obj))

                    # translate group
                    group.transform = Transform(
                        translate=(float(el.attrib["x"]),
                                   float(el.attrib["y"])))

                    # replace use node with group node
                    parent = el.getparent()
                    parent.remove(el)
                    parent.add(group)

                    el = group  # required for recursive defs

                # expand children defs
                TexTextElement._expand_defs(el)
コード例 #15
0
ファイル: test_inkex_paths.py プロジェクト: wachin/inkscape
 def test_transform(self):
     """Transform by a whole matrix"""
     ret = Path("M 100 100 L 110 120 L 140 140 L 300 300")
     ret = ret.transform(Transform(translate=(10, 10)))
     self.assertEqual(str(ret), 'M 110 110 L 120 130 L 150 150 L 310 310')
     ret = ret.transform(Transform(translate=(-10, -10)))
     self.assertEqual(str(ret), 'M 100 100 L 110 120 L 140 140 L 300 300')
     ret = Path('M 5 5 H 10 V 15')
     ret = ret.transform(Transform(rotate=-10))
     self.assertEqual(
         'M 5.79228 4.0558 '
         'L 10.7163 3.18756 '
         'L 12.4528 13.0356', str(ret))
     ret = Path("M 10 10 A 50,50 0 0 1 85.355333,85.355341 L 100 0")
     ret = ret.transform(Transform(scale=10))
     self.assertEqual(str(ret),
                      'M 100 100 A 500 500 0 0 1 853.553 853.553 L 1000 0')
     self.assertRaises(ValueError, Horz([10]).transform, Transform())
コード例 #16
0
ファイル: test_inkex_paths.py プロジェクト: wachin/inkscape
    def test_transformation_preserve_type(self):
        import re
        paths = [
            "M 10 10 A 100 100 0 1 0 100 100 C 10 15 20 20 5 5 Z",
            "m 10 10 a 100 100 0 1 0 100 100 c 10 15 20 20 5 5 z",
            "m 10 10 l 100 200 L 20 30 C 10 20 30 40 11 12",
            "M 10 10 Q 12 13 14 15 T 11 32 T 32 11",
            "m 10 10 q 12 13 14 15 t 11 32 t 32 11",
        ]
        t = Transform(matrix=((1, 2, 3), (4, 5, 6)))
        for path_str in paths:
            path = Path(path_str)
            new_path = path.transform(t)
            cmds = "".join([cmd.letter for cmd in new_path])
            expected = re.sub(r"\d|\s|,", "", path_str)

            self.assertEqual(expected, cmds)
            self.assertAlmostTuple(
                [t.apply_to_point(p) for p in path.control_points],
                list(new_path.control_points))
コード例 #17
0
ファイル: export.py プロジェクト: drayde/svg2shenzhen
    def exportDrillLayer(self, layerPath, pad_template):

        kicad_drill_string = ""

        for layer in self.document.getroot().xpath(layerPath,
                                                   namespaces=inkex.NSS):

            layer_trans = layer.get('transform')
            if layer_trans:
                layer_m = Transform(layer_trans).matrix
            else:
                layer_m = IDENTITY_MATRIX

            nodePath = 'descendant::svg:circle'

            count = 0
            for node in layer.xpath(nodePath, namespaces=inkex.NSS):
                count = count + 1
                cx = float(node.get('cx'))
                cy = float(node.get('cy'))

                radius = float(node.get('r'))
                drill_size = radius * 2

                t = node.get('transform')

                if t:
                    m = Transform(t).matrix
                    trans = (Transform(layer_m) * Transform(m)).matrix
                else:
                    trans = layer_m

                pt = Transform(trans).apply_to_point([cx, cy])
                padCoord = self.coordToKicad(pt)

                kicad_drill_string += pad_template.format(x=padCoord[0],
                                                          y=padCoord[1],
                                                          n=count,
                                                          d=drill_size)

        return kicad_drill_string
コード例 #18
0
ファイル: __init__.py プロジェクト: knifelees3/textext
        def align_to_node(self, ref_node, alignment, relative_scale):
            """
            Aligns the node represented by self to a reference node according to the settings defined by the user
            :param (TexTextElement) ref_node: Reference node subclassed from SvgElement to which self is going to be aligned
            :param (str) alignment: A 2-element string list defining the alignment
            :param (float) relative_scale: Scaling of the new node relative to the scale of the reference node
            """
            from inkex.transforms import Transform
            scale_transform = Transform("scale(%f)" % relative_scale)

            old_transform = Transform(ref_node.transform)

            # Account for vertical flipping of pstoedit nodes when recompiled via pdf2svg and vice versa
            revert_flip = Transform("scale(1)")
            if ref_node.get_meta("pdfconverter") == "pdf2svg":
                revert_flip = Transform(matrix=((1, 0, 0),
                                                (0, -1,
                                                 0)))  # vertical reflection

            composition = old_transform * revert_flip

            composition = scale_transform * composition

            # keep alignment point of drawing intact, calculate required shift
            self.transform = composition

            ref_bb = ref_node.bounding_box()
            x, y, w, h = ref_bb.left, ref_bb.top, ref_bb.width, ref_bb.height
            bb = self.bounding_box()
            new_x, new_y, new_w, new_h = bb.left, bb.top, bb.width, bb.height

            p_old = self._get_pos(x, y, w, h, alignment)
            p_new = self._get_pos(new_x, new_y, new_w, new_h, alignment)

            dx = p_old[0] - p_new[0]
            dy = p_old[1] - p_new[1]

            composition = Transform(translate=(dx, dy)) * composition

            self.transform = composition
            self.set_meta("jacobian_sqrt", str(self.get_jacobian_sqrt()))
コード例 #19
0
 def test_add_transform(self):
     """Test add_TRANSFORM syntax for quickly composing known transforms"""
     tr1 = Transform()
     tr1.add_scale(5.0, 1.0)
     self.assertEqual(str(tr1), 'scale(5, 1)')
     tr1.add_translate(10, 10)
     self.assertEqual(str(tr1), 'matrix(5 0 0 1 50 10)')
コード例 #20
0
    def test_rotation_degrees(self):
        """Test parsing and composition of different rotations"""
        self.assertAlmostEqual(Transform(rotate=30).rotation_degrees(), 30)
        self.assertAlmostEqual(
            Transform(translate=(10, 20)).rotation_degrees(), 0)
        self.assertAlmostEqual(Transform(scale=(1, 1)).rotation_degrees(), 0)

        self.assertAlmostEqual(
            Transform(rotate=35, translate=(10, 20)).rotation_degrees(), 35)
        self.assertAlmostEqual(
            Transform(rotate=35, translate=(10, 20),
                      scale=5).rotation_degrees(), 35)
        self.assertAlmostEqual(
            Transform(rotate=35, translate=(10, 20),
                      scale=(5, 5)).rotation_degrees(), 35)

        def rotation_degrees(**kwargs):
            return Transform(**kwargs).rotation_degrees()

        self.assertRaises(ValueError, rotation_degrees, rotate=35, skewx=1)
        self.assertRaises(ValueError, rotation_degrees, rotate=35, skewy=1)
        self.assertRaises(ValueError,
                          rotation_degrees,
                          rotate=35,
                          scale=(10, 11))
        self.assertRaises(ValueError,
                          rotation_degrees,
                          rotate=35,
                          scale=(10, 11))
コード例 #21
0
    def test_construction_order(self):
        """Test transform kwargs construction order"""
        if not PY3:
            self.skipTest(
                "Construction order is known to fail on python2 (by design).")
            return

        self.assertEqual(str(Transform(scale=2.0, translate=(5, 6))),
                         'matrix(2 0 0 2 5 6)')
        self.assertEqual(str(Transform(scale=2.0, rotate=45)),
                         'matrix(1.41421 1.41421 -1.41421 1.41421 0 0)')

        x, y, angle = 5, 7, 31
        rotation = Transform(rotate=angle)
        translation = Transform(translate=(x, y))

        rotation_then_translation = translation * rotation
        translation_then_rotation = rotation * translation

        tr1 = Transform(rotate=angle, translate=(x, y))
        tr2 = Transform(translate=(x, y), rotate=angle)

        self.assertNotEqual(tr1, tr2)
        self.assertDeepAlmostEqual(tr1.matrix,
                                   rotation_then_translation.matrix)
        self.assertDeepAlmostEqual(tr2.matrix,
                                   translation_then_rotation.matrix)
コード例 #22
0
    def fill_row(self, node):
        #max_line_width = self.svg.unittouu('450mm')
        #x_start = self.svg.unittouu('3mm')
        #y_start = self.svg.unittouu('1600mm') - self.svg.unittouu('3mm')
        #gap_x = gap_y = self.svg.unittouu('10mm')

        svg = self.document.getroot()
        x_start = 0
        y_start = self.svg.unittouu(svg.attrib['height'])
        max_line_width = self.svg.unittouu(svg.get('width'))

        total_width = 0
        total_height = self.total_height

        group = etree.SubElement(self.svg.get_current_layer(),
                                 addNS('g', 'svg'))

        bbox = node.bounding_box()
        x = bbox.left
        y = bbox.top
        node_width = self.options.gap_x + bbox.width

        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 + bbox.height)

            # translation logic
            if node_copy.tag == addNS('path', 'svg'):
                x_delta = x_dest - x
                y_delta = y_dest - y

                path = Path(node_copy.attrib['d'])
                path.translate(x_delta, y_delta, True)
                node_copy.attrib['d'] = str(Path(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]]
                Transform(translation_matrix) * node_copy.transform
            else:
                node_copy.attrib['x'] = str(x_dest)
                node_copy.attrib['y'] = str(y_dest)

            total_width += node_width

        self.total_height += group.bounding_box().height + self.options.gap_y
    def drawLabel(self, group, angle, segment_angle, outer_diameter, labelNum):
        outer_radius = outer_diameter / 2
        label_angle = angle + (segment_angle / 2)
        point = calculatePoint(label_angle, outer_radius)
        matrix = Transform('rotate(' + str(label_angle + 90) + ')').matrix
        matrix_str = str(matrix[0][0]) + "," + str(matrix[0][1])
        matrix_str += "," + str(matrix[1][0]) + "," + str(matrix[1][1]) + ",0,0"
        text = {
            'id': 'text' + str(labelNum),
            #'sodipodi:linespacing': '0%',
            'style': 'font-size: 6px;font-style: normal;font-family: Sans',
            #'transform': 'matrix(' + matrix_str + ')',
            'x': str(point[0]),
            'y': str(point[1]),
            #'xml:space': 'preserve'
            }
        textElement = etree.SubElement(group, inkex.addNS('text', 'svg'), text)
        #tspanElement = etree.Element(
        #    textElement, '{%s}%s' % (svg_uri, 'tspan'), tspan)
        textElement.text = string.printable[labelNum % len(string.printable)]

        self.svg.get_current_layer().append(textElement)
コード例 #24
0
    def effect(self):

        opt = self.options

        if not opt.placeholderid:
            raise inkex.AbortExtension('Please enter the placeholder ID')
        elif not opt.qrcodeid:
            raise inkex.AbortExtension('Please enter the QRCode ID')

        placeholder = self.svg.getElementById(opt.placeholderid)
        qrcode = self.svg.getElementById(opt.qrcodeid)

        if placeholder is None or qrcode is None:
            # Delete the generated qrcode
            qrcode.getparent().remove(qrcode)
            return

        # Reset scale before processing
        qrcode.set('transform', 'scale(1,1)')

        # Get scaling factors
        scalex = placeholder.bounding_box().width  / qrcode.bounding_box().width
        scaley = placeholder.bounding_box().height / qrcode.bounding_box().height

        # Apply scaling and translating
        tr = Transform()
        tr.add_translate(placeholder.bounding_box().left, placeholder.bounding_box().top)
        qrcode.set('transform', tr)
        tr.add_scale(scalex, scaley)
        qrcode.set('transform', tr)

        # Move qrcode inplace of the placeholder
        placeholder.getparent().append(qrcode)

        # Delete the placeholder
        placeholder.getparent().remove(placeholder)
コード例 #25
0
    def recursiveFuseTransform(self,
                               node,
                               transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):
        # Modification by David Burghoff:
        # Since transforms apply to an object's clips, before applying the transform
        # we will need to duplicate the clip path and transform it
        clippathurl = node.get('clip-path')
        if clippathurl is not None and node.get("transform") is not None:
            myn = node
            while not (myn.getparent() == None):  # get svg handle
                myn = myn.getparent()
            svg = myn
            clippath = svg.getElementById(clippathurl[5:-1])
            if clippath is not None:
                d = clippath.duplicate()
                clippathurl = "url(#" + d.get("id") + ")"
                node.set("clip-path", clippathurl)
                for k in d.getchildren():
                    if k.get('transform') is not None:
                        tr = Transform(node.get("transform")) * Transform(
                            k.get('transform'))
                    else:
                        tr = Transform(node.get("transform"))
                    k.set('transform', tr)

        transf = Transform(transf) * Transform(node.get("transform", None))

        if 'transform' in node.attrib:
            del node.attrib['transform']

        node = ApplyTransform.objectToPath(node)

        if transf == NULL_TRANSFORM:
            # Don't do anything if there is effectively no transform applied
            # reduces alerts for unsupported nodes
            pass
        elif 'd' in node.attrib:
            d = node.get('d')
            p = CubicSuperPath(d)
            p = Path(p).to_absolute().transform(transf, True)
            node.set('d', str(Path(CubicSuperPath(p).to_path())))

            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS('polygon', 'svg'),
                inkex.addNS('polyline', 'svg')
        ]:
            points = node.get('points')
            points = points.strip().split(' ')
            for k, p in enumerate(points):
                if ',' in p:
                    p = p.split(',')
                    p = [float(p[0]), float(p[1])]
                    p = transf.apply_to_point(p)
                    p = [str(p[0]), str(p[1])]
                    p = ','.join(p)
                    points[k] = p
            points = ' '.join(points)
            node.set('points', points)

            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS("ellipse", "svg"),
                inkex.addNS("circle", "svg")
        ]:

            def isequal(a, b):
                return abs(a - b) <= transf.absolute_tolerance

            if node.TAG == "ellipse":
                rx = float(node.get("rx"))
                ry = float(node.get("ry"))
            else:
                rx = float(node.get("r"))
                ry = rx

            cx = float(node.get("cx"))
            cy = float(node.get("cy"))
            sqxy1 = (cx - rx, cy - ry)
            sqxy2 = (cx + rx, cy - ry)
            sqxy3 = (cx + rx, cy + ry)
            newxy1 = transf.apply_to_point(sqxy1)
            newxy2 = transf.apply_to_point(sqxy2)
            newxy3 = transf.apply_to_point(sqxy3)

            node.set("cx", (newxy1[0] + newxy3[0]) / 2)
            node.set("cy", (newxy1[1] + newxy3[1]) / 2)
            edgex = math.sqrt(
                abs(newxy1[0] - newxy2[0])**2 + abs(newxy1[1] - newxy2[1])**2)
            edgey = math.sqrt(
                abs(newxy2[0] - newxy3[0])**2 + abs(newxy2[1] - newxy3[1])**2)

            if not isequal(edgex, edgey) and (
                    node.TAG == "circle" or not isequal(newxy2[0], newxy3[0])
                    or not isequal(newxy1[1], newxy2[1])):
                inkex.utils.errormsg(
                    "Warning: Shape %s (%s) is approximate only, try Object to path first for better results"
                    % (node.TAG, node.get("id")))

            if node.TAG == "ellipse":
                node.set("rx", edgex / 2)
                node.set("ry", edgey / 2)
            else:
                node.set("r", edgex / 2)

        # Modficiation by David Burghoff: Added support for lines
        elif node.tag in inkex.addNS('line', 'svg'):
            x1 = node.get('x1')
            x2 = node.get('x2')
            y1 = node.get('y1')
            y2 = node.get('y2')
            p1 = transf.apply_to_point([x1, y1])
            p2 = transf.apply_to_point([x2, y2])
            node.set('x1', str(p1[0]))
            node.set('y1', str(p1[1]))
            node.set('x2', str(p2[0]))
            node.set('y2', str(p2[1]))
            self.scaleStrokeWidth(node, transf)

        elif node.typename in ['Rectangle']:
            x = float(node.get('x'))
            y = float(node.get('y'))
            w = float(node.get('width'))
            h = float(node.get('height'))
            pts = [[x, y], [x + w, y], [x + w, y + h], [x, y + h], [x, y]]
            xs = []
            ys = []
            for p in pts:
                p = transf.apply_to_point(p)
                xs.append(p.x)
                ys.append(p.y)

            node.set('x', str(min(xs)))
            node.set('y', str(min(ys)))
            node.set('width', str(max(xs) - min(xs)))
            node.set('height', str(max(ys) - min(ys)))
            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS('text', 'svg'),
                inkex.addNS('image', 'svg'),
                inkex.addNS('use', 'svg')
        ]:
            inkex.utils.errormsg(
                "Shape %s (%s) not yet supported, try Object to path first" %
                (node.TAG, node.get("id")))

        else:
            # e.g. <g style="...">
            self.scaleStrokeWidth(node, transf)

        for child in node.getchildren():
            self.recursiveFuseTransform(child, transf)
コード例 #26
0
#!/usr/bin/env python3
#
# License: GPL2
# Copyright Mark "Klowner" Riedesel
# https://github.com/Klowner/inkscape-applytransforms
# Modified by David Burghoff

import inkex
import math
from inkex.paths import CubicSuperPath, Path
from inkex.transforms import Transform
from inkex.styles import Style

NULL_TRANSFORM = Transform([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
from lxml import etree


class ApplyTransform(inkex.EffectExtension):
    def __init__(self):
        super(ApplyTransform, self).__init__()

    def effect(self):
        if self.svg.selected:
            for (_, shape) in self.svg.selected.items():
                self.recursiveFuseTransform(shape)
        else:
            self.recursiveFuseTransform(self.document.getroot())

    @staticmethod
    def objectToPath(node):
        if node.tag == inkex.addNS('g', 'svg'):
コード例 #27
0
    def recursiveFuseTransform(self,
                               node,
                               transf=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):

        transf = Transform(transf) * Transform(node.get("transform", None))

        if 'transform' in node.attrib:
            del node.attrib['transform']

        node = ApplyTransform.objectToPath(node)

        if transf == NULL_TRANSFORM:
            # Don't do anything if there is effectively no transform applied
            # reduces alerts for unsupported nodes
            pass
        elif 'd' in node.attrib:
            d = node.get('d')
            p = CubicSuperPath(d)
            p = Path(p).to_absolute().transform(transf, True)
            node.set('d', Path(CubicSuperPath(p).to_path()))

            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS('polygon', 'svg'),
                inkex.addNS('polyline', 'svg')
        ]:
            points = node.get('points')
            points = points.strip().split(' ')
            for k, p in enumerate(points):
                if ',' in p:
                    p = p.split(',')
                    p = [float(p[0]), float(p[1])]
                    p = transf.apply_to_point(p)
                    p = [str(p[0]), str(p[1])]
                    p = ','.join(p)
                    points[k] = p
            points = ' '.join(points)
            node.set('points', points)

            self.scaleStrokeWidth(node, transf)

        elif node.tag in [
                inkex.addNS("ellipse", "svg"),
                inkex.addNS("circle", "svg")
        ]:

            def isequal(a, b):
                return abs(a - b) <= transf.absolute_tolerance

            if node.TAG == "ellipse":
                rx = float(node.get("rx"))
                ry = float(node.get("ry"))
            else:
                rx = float(node.get("r"))
                ry = rx

            cx = float(node.get("cx"))
            cy = float(node.get("cy"))
            sqxy1 = (cx - rx, cy - ry)
            sqxy2 = (cx + rx, cy - ry)
            sqxy3 = (cx + rx, cy + ry)
            newxy1 = transf.apply_to_point(sqxy1)
            newxy2 = transf.apply_to_point(sqxy2)
            newxy3 = transf.apply_to_point(sqxy3)

            node.set("cx", (newxy1[0] + newxy3[0]) / 2)
            node.set("cy", (newxy1[1] + newxy3[1]) / 2)
            edgex = math.sqrt(
                abs(newxy1[0] - newxy2[0])**2 + abs(newxy1[1] - newxy2[1])**2)
            edgey = math.sqrt(
                abs(newxy2[0] - newxy3[0])**2 + abs(newxy2[1] - newxy3[1])**2)

            if not isequal(edgex, edgey) and (
                    node.TAG == "circle" or not isequal(newxy2[0], newxy3[0])
                    or not isequal(newxy1[1], newxy2[1])):
                inkex.utils.errormsg(
                    "Warning: Shape %s (%s) is approximate only, try Object to path first for better results"
                    % (node.TAG, node.get("id")))

            if node.TAG == "ellipse":
                node.set("rx", edgex / 2)
                node.set("ry", edgey / 2)
            else:
                node.set("r", edgex / 2)

        elif node.tag in [
                inkex.addNS('rect', 'svg'),
                inkex.addNS('text', 'svg'),
                inkex.addNS('image', 'svg'),
                inkex.addNS('use', 'svg')
        ]:
            inkex.utils.errormsg(
                "Shape %s (%s) not yet supported, try Object to path first" %
                (node.TAG, node.get("id")))

        else:
            # e.g. <g style="...">
            self.scaleStrokeWidth(node, transf)

        for child in node.getchildren():
            self.recursiveFuseTransform(child, transf)
コード例 #28
0
    def recursively_traverse_svg(self, node_list,
                                 trans_current=Transform(((1.0, 0.0, 0.0), (0.0, -1.0, 0.0))),
                                 parent_visibility='visible'):
        """
    Recursively traverse the svg file to plot out all of the
    paths.  The function keeps track of the composite transformation
    that should be applied to each path.

    This function handles path, group, line, rect, polyline, polygon,
    circle, ellipse and use (clone) elements. Notable elements not
    handled include text.  Unhandled elements should be converted to
    paths in Inkscape.

    TODO: There's a lot of inlined code in the eggbot version of this
    that would benefit from the Entities method of dealing with things.
    """
        for node in node_list:
            # Ignore invisible nodes
            v = node.get('visibility', parent_visibility)
            if v == 'inherit':
                v = parent_visibility
            if v == 'hidden' or v == 'collapse':
                pass

            # first apply the current matrix transform to this node's transform

            trans = Transform(node.get("transform"))
            trans_new = trans_current * trans

            if node.tag == inkex.addNS('g', 'svg') or node.tag == 'g':
                if node.get(inkex.addNS('groupmode', 'inkscape')) == 'layer':
                    node.get(inkex.addNS('label', 'inkscape'))

                self.recursively_traverse_svg(node, trans_new, parent_visibility=v)
            elif node.tag == inkex.addNS('use', 'svg') or node.tag == 'use':
                ref_id = node.get(inkex.addNS('href', 'xlink'))
                if ref_id:
                    # [1:] to ignore leading '#' in reference
                    path = '//*[@id="%s"]' % ref_id[1:]
                    ref_node = node.xpath(path)
                    if ref_node:
                        x = float(node.get('x', '0'))
                        y = float(node.get('y', '0'))
                        # Note: the transform has already been applied
                        if (x != 0) or (y != 0):
                            trans_new2 = trans_new * Transform('translate(%f,%f)' % (x, y))
                        else:
                            trans_new2 = trans_new
                        v = node.get('visibility', v)
                        self.recursively_traverse_svg(ref_node, trans_new2, parent_visibility=v)
                    else:
                        pass
                else:
                    pass
            elif not isinstance(node.tag, str):
                pass
            else:
                entity = self.make_entity(node, trans_new)
                if entity is None:
                    inkex.errormsg(
                        'Warning: unable to draw object, please convert it to a path first. objID: ' + node.get('id'))
コード例 #29
0
 def parse(self):
     # 0.28222 scale determined by comparing pixels-per-mm in a default Inkscape file.
     # self.svgWidth = self.getLength('width', 354) * 0.28222
     # self.svgHeight = self.getLength('height', 354) * 0.28222
     self.recursively_traverse_svg(self.svg, Transform(((1.0, 0.0, 0), (0.0, -1.0, self.svgHeight))))
コード例 #30
0
    def exportEdgeCut(self, kicad_mod=False):
        x0 = 0
        y0 = 0
        mirror = 1.0

        line_type = "fp_line" if kicad_mod else "gr_line"

        kicad_edgecut_string = ""

        i = 0
        layerPath = '//svg:g[@inkscape:groupmode="layer"]'

        if (self.options.autoflatten):
            self.flatten_bezier()

        for layer in self.document.getroot().xpath(layerPath,
                                                   namespaces=inkex.NSS):
            i += 1

            label_attrib_name = "{%s}label" % layer.nsmap['inkscape']
            if label_attrib_name not in layer.attrib:
                continue

            layer_name = (layer.attrib[label_attrib_name])

            if layer_name != "Edge.Cuts":
                continue

            layer_trans = layer.get('transform')
            if layer_trans:
                layer_m = Transform(layer_trans).matrix
            else:
                layer_m = IDENTITY_MATRIX

            nodePath = (
                '//svg:g[@inkscape:groupmode="layer"][%d]/descendant::svg:path'
            ) % i
            for node in self.document.getroot().xpath(nodePath,
                                                      namespaces=inkex.NSS):
                p = node.path.to_arrays()

                points = []
                if p:
                    #sanity check
                    if p[0][0] == 'M':
                        t = node.get('transform')
                        if t:
                            trans = (Transform(layer_m) * Transform(t)).matrix
                        else:
                            trans = layer_m

                        for path in p:
                            if path[0] != "Z":
                                x = (path[1][0])
                                y = (path[1][1])
                                xy = Transform(trans).apply_to_point([x, y])
                                points.append(
                                    self.coordToKicad([(xy[0] - x0),
                                                       xy[1] * mirror - y0]))

                        points_count = len(points)
                        points.append(points[0])

                        for x in range(0, points_count):
                            kicad_edgecut_string = kicad_edgecut_string + (
                                "(%s (start %f %f) (end %f %f) (layer Edge.Cuts) (width 0.1))\n"
                                % (line_type, points[x][0], points[x][1],
                                   points[x + 1][0], points[x + 1][1]))

        return kicad_edgecut_string