Esempio n. 1
0
    def test_to_curves(self):
        """Segments can become curves"""
        self.assertRaises(ValueError, Move(0, 0).to_curve, None)
        self.assertEqual(
            Line(10, 10).to_curve(Vector2d(10, 5)), (10, 5, 10, 10, 10, 10))
        self.assertEqual(
            Horz(10).to_curve(Vector2d(10, 5)), (10, 5, 10, 5, 10, 5))
        self.assertEqual(
            Vert(10).to_curve(Vector2d(5, 10)), (5, 10, 5, 10, 5, 10))
        self.assertEqual(
            Curve(5, 5, 10, 10, 4, 4).to_curve(Vector2d(0, 0)),
            (5, 5, 10, 10, 4, 4))

        self.assertEqual(
            Smooth(10, 10, 4, 4).to_curve(Vector2d(4, 4), Vector2d(10, 10)),
            (-2, -2, 10, 10, 4, 4),
        )

        self.assertAlmostTuple(
            Quadratic(10, 10, 4, 4).to_curve(Vector2d(0, 0)).args,
            (6.666666666666666, 6.666666666666666, 8, 8, 4, 4),
        )

        self.assertAlmostTuple(
            TepidQuadratic(4, 4).to_curve(Vector2d(14, 19), Vector2d(11,
                                                                     12)).args,
            #            (20.666666666666664, 30, 17.333333333333332, 25, 4, 4),
            (15.999999999999998, 23.666666666666664, 12.666666666666666,
             18.666666666666664, 4, 4),
        )

        curves = list(Arc(50, 50, 0, 0, 1, 85, 85).to_curves(Vector2d(0, 0)))
        self.assertEqual(len(curves), 3)
        self.assertAlmostTuple(
            curves[0].args,
            (19.77590700610636, -5.4865851247611115, 38.18634924829132,
             -10.4196482558544, 55.44095225512604, -5.796291314453416))
        self.assertAlmostTuple(
            curves[1].args,
            (72.69555526196076, -1.172934373052433, 86.17293437305243,
             12.30444473803924, 90.79629131445341, 29.559047744873958))
        self.assertAlmostTuple(
            curves[2].args,
            (95.41964825585441, 46.81365075170867, 90.4865851247611,
             65.22409299389365, 77.85533905932738, 77.85533905932738))

        def apply_to_curve(obj):
            obj.to_curve(Vector2d())

        def apply_to_curves(obj):
            obj.to_curve(Vector2d())

        self.assertRaises(ValueError, apply_to_curve, ZoneClose())
        self.assertRaises(ValueError, apply_to_curves, zoneClose())

        self.assertRaises(ValueError, apply_to_curve, Move(0, 0))
        self.assertRaises(ValueError, apply_to_curves, move(0, 0))
Esempio n. 2
0
    def test_transformation(self):
        t = Transform(matrix=((1, 2, 3), (4, 5, 6)))

        first = Vector2d()
        prev = Vector2d(31, 97)
        prev_prev = Vector2d(5, 7)

        for Cmd in (Line, Move, Curve, Smooth, Quadratic, TepidQuadratic, Arc):
            random_seg = self.get_random_cmd(Cmd)
            self.assertTrue(random_seg.transform(t)
                            is not random_seg)  # transform returns copy
            self.assertEqual(
                random_seg.transform(t).name,
                Cmd.name)  # transform does not change Command type

            T = Transform()
            T.add_translate(10, 20)
            A = [
                T.apply_to_point(p)
                for p in random_seg.control_points(first, prev, prev_prev)
            ]
            first2, prev2, prev_prev2 = (T.apply_to_point(p)
                                         for p in (first, prev, prev_prev))
            B = list(
                random_seg.translate(Vector2d(10, 20)).control_points(
                    first2, prev2, prev_prev2))
            self.assertAlmostTuple(A, B)

            T = Transform()
            T.add_scale(10, 20)
            A = [
                T.apply_to_point(p)
                for p in random_seg.control_points(first, prev, prev_prev)
            ]
            first2, prev2, prev_prev2 = (T.apply_to_point(p)
                                         for p in (first, prev, prev_prev))
            B = list(
                random_seg.scale(
                    (10, 20)).control_points(first2, prev2, prev_prev2))
            self.assertAlmostTuple(A, B)

            T = Transform()
            T.add_rotate(35, 15, 28)
            A = [
                T.apply_to_point(p)
                for p in random_seg.control_points(first, prev, prev_prev)
            ]
            first2, prev2, prev_prev2 = (T.apply_to_point(p)
                                         for p in (first, prev, prev_prev))
            B = list(
                random_seg.rotate(35, Vector2d(15, 28)).control_points(
                    first2, prev2, prev_prev2))
            self.assertAlmostTuple(A, B)
Esempio n. 3
0
    def process_path(self, node, transform):
        """Process the given element into a plotter path"""
        pen = self.get_pen_number(node)
        speed = self.get_pen_speed(node)
        force = self.get_pen_force(node)

        path = node.path.to_absolute()\
                   .transform(node.composed_transform())\
                   .transform(transform)\
                   .to_superpath()
        if path:
            cspsubdiv(path, self.flat)
            # path to HPGL commands
            oldPosX = 0.0
            oldPosY = 0.0
            for singlePath in path:
                cmd = 'PU'
                for singlePathPoint in singlePath:
                    posX, posY = singlePathPoint[1]
                    # check if point is repeating, if so, ignore
                    if int(round(posX)) != int(round(oldPosX)) \
                            or int(round(posY)) != int(round(oldPosY)):
                        self.processOffset(cmd, Vector2d(posX, posY), pen,
                                           speed, force)
                        cmd = 'PD'
                        oldPosX = posX
                        oldPosY = posY
                # perform overcut
                if self.overcut > 0.0 and not self.dryRun:
                    # check if last and first points are the same, otherwise the path
                    # is not closed and no overcut can be performed
                    if int(round(oldPosX)) == int(round(singlePath[0][1][0])) and\
                                        int(round(oldPosY)) == int(round(singlePath[0][1][1])):
                        overcutLength = 0
                        for singlePathPoint in singlePath:
                            posX, posY = singlePathPoint[1]
                            # check if point is repeating, if so, ignore
                            if int(round(posX)) != int(round(oldPosX)) or int(round(posY))\
                                                                            != int(round(oldPosY)):
                                overcutLength += (Vector2d(posX, posY) -
                                                  (oldPosX, oldPosY)).length
                                if overcutLength >= self.overcut:
                                    newEndPoint = self.changeLength(Vector2d(oldPosX, oldPosY),\
                                            Vector2d(posX, posY), - (overcutLength - self.overcut))
                                    self.processOffset(cmd, newEndPoint, pen,
                                                       speed, force)
                                    break
                                self.processOffset(cmd, Vector2d(posX, posY),
                                                   pen, speed, force)
                                oldPosX = posX
                                oldPosY = posY
Esempio n. 4
0
    def test_binary_operators(self):
        """Test binary operators for vector2d"""
        vec1 = Vector2d(15, 22)
        vec2 = Vector2d(5, 3)

        self.assertTrue((vec1 - vec2).is_close((10, 19)))
        self.assertTrue((vec1 - (5, 3)).is_close((10, 19)))
        self.assertTrue(((15, 22) - vec2).is_close((10, 19)))
        self.assertTrue((vec1 + vec2).is_close((20, 25)))
        self.assertTrue((vec1 + (5, 3)).is_close((20, 25)))
        self.assertTrue(((15, 22) + vec2).is_close((20, 25)))
        self.assertTrue((vec1 * 2).is_close((30, 44)))
        self.assertTrue((2 * vec1).is_close((30, 44)))
        self.assertTrue((vec1 / 2).is_close((7.5, 11)))
        self.assertTrue((vec1.__div__(2)).is_close((7.5, 11)))
        self.assertTrue((vec1 // 2).is_close((7.5, 11)))
Esempio n. 5
0
 def test_assign(self):
     """Test vector2d assignement"""
     vec = Vector2d(10, 20)
     vec.assign(5, 10)
     self.assertAlmostTuple(vec, (5, 10))
     vec.assign((7, 11))
     self.assertAlmostTuple(vec, (7, 11))
Esempio n. 6
0
 def test_polar_operations(self):
     """Test polar coordinates operations"""
     #               x  y  r  pi
     equivilents = [(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, -1),
                    (0, 0, 0, 0.5), (1, 0, 1, 0), (0, 1, 1, 0.5),
                    (0, -1, 1, -0.5), (3, 0, 3, 0), (0, 3, 3, 0.5),
                    (0, -3, 3, -0.5), (sqrt(2), sqrt(2), 2, 0.25),
                    (-sqrt(2), sqrt(2), 2, 0.75),
                    (sqrt(2), -sqrt(2), 2, -0.25),
                    (-sqrt(2), -sqrt(2), 2, -0.75)]
     for x, y, r, t in equivilents:
         theta = t * pi if r != 0 else None
         for ts in [0, 2, -2]:
             ctx_msg = 'Test values are x: {} y: {} r: {} θ: {} * pi'.format(
                 x, y, r, t + ts)
             polar = Vector2d.from_polar(r, (t + ts) * pi)
             cart = Vector2d(x, y)
             self.assertEqual(cart.length, r, msg=ctx_msg)
             self.assertEqual(polar.length, r, msg=ctx_msg)
             self.assertAlmostEqual(cart.angle,
                                    theta,
                                    msg=ctx_msg,
                                    delta=1e-12)
             self.assertAlmostEqual(polar.angle,
                                    theta,
                                    msg=ctx_msg,
                                    delta=1e-12)
             self.assertEqual(cart.to_polar_tuple(), (r, cart.angle),
                              msg=ctx_msg)
             self.assertEqual(polar.to_polar_tuple(), (r, polar.angle),
                              msg=ctx_msg)
             self.assertEqual(cart.to_tuple(), (x, y), msg=ctx_msg)
             self.assertAlmostEqual(polar.to_tuple()[0],
                                    x,
                                    msg=ctx_msg,
                                    delta=1e-12)
             self.assertAlmostEqual(polar.to_tuple()[1],
                                    y,
                                    msg=ctx_msg,
                                    delta=1e-12)
     # Test special handling of from_polar with None theta
     self.assertEqual(Vector2d.from_polar(0, None).to_tuple(), (0.0, 0.0))
     self.assertIsNone(Vector2d.from_polar(4, None))
Esempio n. 7
0
    def test_vector_creation(self):
        """Test Vector2D creation"""
        vec0 = Vector2d(15, 22)
        self.assertEqual(vec0.x, 15)
        self.assertEqual(vec0.y, 22)

        vec1 = Vector2d()
        self.assertEqual(vec1.x, 0)
        self.assertEqual(vec1.y, 0)

        vec2 = Vector2d((17, 32))
        self.assertEqual(vec2.x, 17)
        self.assertEqual(vec2.y, 32)

        vec3 = Vector2d(vec0)
        self.assertEqual(vec3.x, 15)
        self.assertEqual(vec3.y, 22)

        self.assertRaises(ValueError, Vector2d, (1))
        self.assertRaises(ValueError, Vector2d, (1, 2, 3))
Esempio n. 8
0
 def _path_points(self, elt):
     'Return a list of all points on a path (endpoints, not control points).'
     pts = set()
     first = None
     prev = Vector2d()
     for cmd in elt.path.to_absolute():
         if first is None:
             first = cmd.end_point(first, prev)
         ep = cmd.end_point(first, prev)
         pts.add((ep.x, ep.y))
         prev = ep
     return pts
Esempio n. 9
0
 def test_ioperators(self):
     """Test operators for vector2d"""
     vec0 = vec = Vector2d(15, 22)
     vec += (1, 1)
     self.assertTrue(vec.is_close((16, 23)))
     vec -= (10, 20)
     self.assertTrue(vec.is_close((6, 3)))
     vec *= 5
     self.assertTrue(vec.is_close((30, 15)))
     vec /= 90
     self.assertTrue(vec.is_close((1.0 / 3, 1.0 / 6)))
     vec //= 1.0 / 3
     self.assertTrue(vec.is_close((1, 0.5)))
     self.assertFalse(vec0.is_close((15, 22)))
     self.assertTrue(vec0.is_close(vec))
Esempio n. 10
0
    def test_absolute_relative(self):
        absolutes = Line, Move, Curve, Smooth, Quadratic, TepidQuadratic, Arc, Vert, Horz, ZoneClose
        relatives = line, move, curve, smooth, quadratic, tepidQuadratic, arc, vert, horz, zoneClose

        zero = Vector2d()
        for R, A in zip(relatives, absolutes):
            rel = self.get_random_cmd(R)
            ab = self.get_random_cmd(A)

            self.assertTrue(rel.is_relative)
            self.assertTrue(ab.is_absolute)

            self.assertFalse(rel.is_absolute)
            self.assertFalse(ab.is_relative)

            self.assertEqual(type(rel.to_absolute(zero)), A)
            self.assertEqual(type(ab.to_relative(zero)), R)
            self.assertTrue(rel.to_relative(zero) is not rel)
            self.assertTrue(ab.to_absolute(zero) is not ab)
Esempio n. 11
0
    def effect(self):
        for node in self.svg.selection.filter(inkex.PathElement):
            result = Path()
            prev = Vector2d()
            start = None
            for seg in node.path.to_absolute():
                if start is None:
                    start = seg.end_point(start, prev)
                if isinstance(seg, Curve):
                    result += [
                        Move(seg.x2, seg.y2),
                        Line(prev.x, prev.y),
                        Move(seg.x3, seg.y3),
                        Line(seg.x4, seg.y4),
                    ]
                elif isinstance(seg, Quadratic):
                    result += [
                        Move(seg.x2, seg.y2),
                        Line(prev.x, prev.y),
                        Move(seg.x2, seg.y2),
                        Line(seg.x3, seg.y3)
                    ]
                prev = seg.end_point(start, prev)

            if not result:
                continue

            elem = node.getparent().add(inkex.PathElement())
            elem.path = result.transform(node.transform)
            elem.style = {
                'stroke-linejoin': 'miter',
                'stroke-width': '1.0px',
                'stroke-opacity': '1.0',
                'fill-opacity': '1.0',
                'stroke': '#000000',
                'stroke-linecap': 'butt',
                'fill': 'none'
            }
Esempio n. 12
0
    def makeface(last, segment, facegroup, delx, dely):
        """translate path segment along vector"""
        elem = facegroup.add(inkex.PathElement())

        npt = segment.translate([delx, dely])

        # reverse direction of path segment
        if isinstance(segment, Curve):
            rev = Curve(npt.x3, npt.y3, npt.x2, npt.y2, last[0] + delx,
                        last[1] + dely)
        elif isinstance(segment, Line):
            rev = Line(last[0] + delx, last[1] + dely)
        else:
            raise RuntimeError("Unexpected segment type {}".format(
                type(segment)))

        elem.path = inkex.Path([
            Move(last[0], last[1]),
            segment,
            npt.to_line(Vector2d()),
            rev,
            ZoneClose(),
        ])
Esempio n. 13
0
    def getHpgl(self):
        """Return the HPGL instructions"""
        # dryRun to find edges
        transform = Transform(
            [[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, 0.0],
             [0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, 0.0]])
        transform.add_rotate(int(self.options.orientation))

        self.vData = [['', 'False', 0], ['', 'False', 0], ['', 'False', 0],
                      ['', 'False', 0]]
        self.process_group(self.doc, transform)
        if self.divergenceX == 'False' or self.divergenceY == 'False' or self.sizeX == 'False' or self.sizeY == 'False':
            raise NoPathError("No paths found")
        # live run
        self.dryRun = False
        # move drawing according to various modifiers
        if self.options.autoAlign:
            if self.options.center:
                self.offsetX -= (self.sizeX - self.divergenceX) / 2
                self.offsetY -= (self.sizeY - self.divergenceY) / 2
        else:
            self.divergenceX = 0.0
            self.divergenceY = 0.0
            if self.options.center:
                if self.options.orientation == '0':
                    self.offsetX -= (self.docWidth * self.scaleX) / 2
                    self.offsetY += (self.docHeight * self.scaleY) / 2
                if self.options.orientation == '90':
                    self.offsetY += (self.docWidth * self.scaleX) / 2
                    self.offsetX += (self.docHeight * self.scaleY) / 2
                if self.options.orientation == '180':
                    self.offsetX += (self.docWidth * self.scaleX) / 2
                    self.offsetY -= (self.docHeight * self.scaleY) / 2
                if self.options.orientation == '270':
                    self.offsetY -= (self.docWidth * self.scaleX) / 2
                    self.offsetX -= (self.docHeight * self.scaleY) / 2
            else:
                if self.options.orientation == '0':
                    self.offsetY += self.docHeight * self.scaleY
                if self.options.orientation == '90':
                    self.offsetY += self.docWidth * self.scaleX
                    self.offsetX += self.docHeight * self.scaleY
                if self.options.orientation == '180':
                    self.offsetX += self.docWidth * self.scaleX
        if not self.options.center and self.toolOffset > 0.0:
            self.offsetX += self.toolOffset
            self.offsetY += self.toolOffset

        # initialize transformation matrix and cache
        transform = Transform(
            [[
                self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0,
                -float(self.divergenceX) + self.offsetX
            ],
             [
                 0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY,
                 -float(self.divergenceY) + self.offsetY
             ]])
        transform.add_rotate(int(self.options.orientation))
        self.vData = [['', 'False', 0], ['', 'False', 0], ['', 'False', 0],
                      ['', 'False', 0]]
        # add move to zero point and precut
        if self.toolOffset > 0.0 and self.options.precut:
            if self.options.center:
                # position precut outside of drawing plus one time the tooloffset
                if self.offsetX >= 0.0:
                    precutX = self.offsetX + self.toolOffset
                else:
                    precutX = self.offsetX - self.toolOffset
                if self.offsetY >= 0.0:
                    precutY = self.offsetY + self.toolOffset
                else:
                    precutY = self.offsetY - self.toolOffset
                self.processOffset('PU', Vector2d(precutX,
                                                  precutY), self.options.pen,
                                   self.options.speed, self.options.force)
                self.processOffset(
                    'PD', Vector2d(precutX, precutY + self.toolOffset * 8),
                    self.options.pen, self.options.speed, self.options.force)
            else:
                self.processOffset('PU', Vector2d(0, 0), self.options.pen,
                                   self.options.speed, self.options.force)
                self.processOffset('PD', Vector2d(0, self.toolOffset * 8),
                                   self.options.pen, self.options.speed,
                                   self.options.force)
        # start conversion
        self.process_group(self.doc, transform)
        # shift an empty node in in order to process last node in cache
        if self.toolOffset > 0.0 and not self.dryRun:
            self.processOffset('PU', Vector2d(0, 0), 0, 0, 0)
        return self.hpgl
Esempio n. 14
0
 def test_getitem(self):
     """Test getitem for Vector2D"""
     vec = Vector2d(10, 20)
     self.assertEqual(len(vec), 2)
     self.assertEqual(vec[0], 10)
     self.assertEqual(vec[1], 20)
Esempio n. 15
0
 def changeLength(self, p1, p2, offset):
     """change length of line"""
     if p1.x == p2.x and p1.y == p2.y:  # abort if points are the same
         return p1
     return Vector2d(DirectedLineSegment(p2, p1).point_at_length(-offset))
Esempio n. 16
0
 def test_representations(self):
     """Test Vector2D Repr"""
     self.assertEqual(str(Vector2d(1, 2)), "1, 2")
     self.assertEqual(repr(Vector2d(1, 2)), "Vector2d(1, 2)")
     self.assertEqual(Vector2d(1, 2).to_tuple(), (1, 2))
Esempio n. 17
0
 def processOffset(self, cmd, point, pen, speed, force):
     """ Calculate offset correction """
     if self.toolOffset == 0.0 or self.dryRun:
         self.storePoint(cmd, point, pen, speed, force)
     else:
         # insert data into cache
         self.vData.pop(0)
         self.vData.insert(3, [cmd, point, pen, speed, force])
         # decide if enough data is available
         if self.vData[2][1] != 'False':
             if self.vData[1][1] == 'False':
                 self.storePoint(self.vData[2][0], self.vData[2][1],
                                 self.vData[2][2], self.vData[2][3],
                                 self.vData[2][4])
             else:
                 # perform tool offset correction (It's a *tad* complicated, if you want
                 #                     to understand it draw the data as lines on paper)
                 if self.vData[2][0] == 'PD':
                     # If the 3rd entry in the cache is a pen down command,
                     #             make the line longer by the tool offset
                     pointThree = self.changeLength(self.vData[1][1],
                                                    self.vData[2][1],
                                                    self.toolOffset)
                     self.storePoint('PD', pointThree, self.vData[2][2],
                                     self.vData[2][3], self.vData[2][4])
                 elif self.vData[0][1] != 'False':
                     # Elif the 1st entry in the cache is filled with data and the 3rd entry
                     #   is a pen up command shift the 3rd entry by the current tool offset
                     #   position according to the 2nd command
                     pointThree = self.changeLength(self.vData[0][1],
                                                    self.vData[1][1],
                                                    self.toolOffset)
                     pointThree = self.vData[2][1] - (self.vData[1][1] -
                                                      pointThree)
                     self.storePoint('PU', pointThree, self.vData[2][2],
                                     self.vData[2][3], self.vData[2][4])
                 else:
                     # Else just write the 3rd entry
                     pointThree = self.vData[2][1]
                     self.storePoint('PU', pointThree, self.vData[2][2],
                                     self.vData[2][3], self.vData[2][4])
                 if self.vData[3][0] == 'PD':
                     # If the 4th entry in the cache is a pen down command guide tool to next
                     #           line with a circle between the prolonged 3rd and 4th entry
                     originalSegment = DirectedLineSegment(
                         self.vData[2][1], self.vData[3][1])
                     if originalSegment.length >= self.toolOffset:
                         pointFour = self.changeLength(originalSegment.end,\
                                                     originalSegment.start, - self.toolOffset)
                     else:
                         pointFour = self.changeLength(originalSegment.start,\
                                 originalSegment.end, self.toolOffset - originalSegment.length)
                     # get angle start and angle vector
                     angleStart = DirectedLineSegment(
                         self.vData[2][1], pointThree).angle
                     angleVector = DirectedLineSegment(self.vData[2][1], pointFour).angle\
                                                                                 - angleStart
                     # switch direction when arc is bigger than 180°
                     if angleVector > math.pi:
                         angleVector -= math.pi * 2
                     elif angleVector < -math.pi:
                         angleVector += math.pi * 2
                     # draw arc
                     if angleVector >= 0:
                         angle = angleStart + self.toolOffsetFlat
                         while angle < angleStart + angleVector:
                             self.storePoint('PD', self.vData[2][1] + self.toolOffset *\
                                 Vector2d(math.cos(angle), math.sin(angle)), self.vData[2][2], self.vData[2][3], self.vData[2][4])
                             angle += self.toolOffsetFlat
                     else:
                         angle = angleStart - self.toolOffsetFlat
                         while angle > angleStart + angleVector:
                             self.storePoint('PD', self.vData[2][1] + self.toolOffset *\
                                 Vector2d(math.cos(angle), math.sin(angle)), self.vData[2][2], self.vData[2][3], self.vData[2][4])
                             angle -= self.toolOffsetFlat
                     self.storePoint('PD', pointFour, self.vData[3][2],
                                     self.vData[2][3], self.vData[2][4])
Esempio n. 18
0
 def test_unary_operators(self):
     """Test unary operators"""
     vec = Vector2d(1, 2)
     self.assertTrue((-vec).is_close((-1, -2)))
     self.assertTrue((+vec).is_close(vec))
     self.assertTrue(+vec is not vec)  # returned value is a copy
Esempio n. 19
0
 def test_svg_center_position(self):
     """SVG with namedview has a center position"""
     doc = svg_file(self.data_file('svg', 'multilayered-test.svg'))
     self.assertTrue(doc.namedview.center.is_close((30.714286, 520.0)))
     self.assertTrue(svg().namedview.center.is_close(Vector2d()))
Esempio n. 20
0
    def test_to_line(self):
        self.assertEqual(Vert(3).to_line(Vector2d(5, 11)), Line(5, 3))
        self.assertEqual(Horz(3).to_line(Vector2d(5, 11)), Line(3, 11))

        self.assertEqual(vert(3).to_line(Vector2d(5, 11)), Line(5, 14))
        self.assertEqual(horz(3).to_line(Vector2d(5, 11)), Line(8, 11))
Esempio n. 21
0
 def apply_to_curves(obj):
     obj.to_curve(Vector2d())
Esempio n. 22
0
    def effect(self):
        path_num = 0
        elems = []
        npaths = []
        sstr = None
        for selem in self.svg.selection.filter(PathElement):
            elems.append(copy.deepcopy(selem))
        if len(elems) == 0:
            raise inkex.AbortExtension("Nothing selected")
        for elem in elems:
            escale = 1.0
            npaths.clear()
            #inkex.utils.debug(elem.attrib)
            if 'style' in elem.attrib:
                sstr = elem.attrib['style']
            if 'transform' in elem.attrib:
                transforms = elem.attrib['transform'].split()
                for tf in transforms:
                    if tf.startswith('scale'):
                        escale = float(tf.split('(')[1].split(')')[0])
                if sstr != None:
                    lsstr = sstr.split(';')
                    for stoken in range(len(lsstr)):
                        if lsstr[stoken].startswith('stroke-width'):
                            swt = lsstr[stoken].split(':')[1]
                            if not swt[2:].isalpha(
                            ):  # is value expressed in units (e.g. px)?
                                swf = str(float(swt) * escale)  # no. scale it
                                lsstr[stoken] = lsstr[stoken].replace(swt, swf)
                        if lsstr[stoken].startswith('stroke-miterlimit'):
                            swt = lsstr[stoken].split(':')[1]
                            if not swt[2:].isalpha(
                            ):  # is value expressed in units (e.g. px)?
                                swf = str(float(swt) * escale)  # no. scale it
                                lsstr[stoken] = lsstr[stoken].replace(swt, swf)
                    sstr = ";".join(lsstr)
                else:
                    sstr = None
                elem.apply_transform()
            xbound, ybound = elem.bounding_box()  # Get bounds of this element
            xmin, xmax = xbound
            ymin, ymax = ybound
            ntotal = len(elem.path)
            nodecnt = 0
            startx = 0
            starty = ymax + 10 * escale
            endx = 0
            endy = starty
            xoffset = 0
            orig_sx = 0
            orig_sy = 0
            orig_ex = 0
            orig_ey = 0
            sx1 = 0
            sy1 = 0
            orig_length = 0
            prev = Vector2d()
            for ptoken in elem.path.to_absolute(
            ):  # For each point in the path
                startx = xmin + xoffset
                if ptoken.letter == 'M':  # Starting a new line
                    orig_sx = ptoken.x
                    orig_sy = ptoken.y
                    cd = Path()
                    cd.append(Move(startx, starty))
                    sx1 = orig_sx
                    sy1 = orig_sy
                else:
                    if last_letter != 'M':
                        orig_sx = orig_ex
                        orig_sy = orig_ey

                    if ptoken.letter == 'L':
                        orig_ex = ptoken.x
                        orig_ey = ptoken.y
                        orig_length = math.sqrt((orig_sx - orig_ex)**2 +
                                                (orig_sy - orig_ey)**2)
                        endx = startx + orig_length
                        cd.append(Line(endx, endy))
                    elif ptoken.letter == 'H':
                        orig_ey = ptoken.to_line(prev).y
                        orig_length = abs(orig_sx - ptoken.x)
                        orig_ex = ptoken.x
                        endx = startx + orig_length
                        cd.append(Line(endx, endy))
                    elif ptoken.letter == 'V':
                        orig_ex = ptoken.to_line(prev).x
                        orig_length = abs(orig_sy - ptoken.y)
                        orig_ey = ptoken.y
                        endx = startx + orig_length
                        cd.append(Line(endx, endy))
                    elif ptoken.letter == 'Z':
                        orig_ex = sx1
                        orig_ey = sy1
                        orig_length = math.sqrt((orig_sx - orig_ex)**2 +
                                                (orig_sy - orig_ey)**2)
                        endx = startx + orig_length
                        cd.append(Line(endx, endy))
                    elif ptoken.letter == 'C':
                        bez = ptoken.to_bez()  # [[x0,y0][x1,y1][x2,y2][x3,y3]]
                        bez.insert(0, [prev.x, prev.y])
                        orig_ex = bez[3][0]  #x3
                        orig_ey = bez[3][1]  #y3
                        orig_length = inkex.bezier.bezierlength(bez)
                        endx = startx + orig_length
                        cd.append(Line(endx, endy))
                    else:
                        raise inkex.AbortExtension(
                            "Unknown letter - {0}".format(ptoken.letter))
                nodecnt = nodecnt + 1
                if ptoken.letter != 'M':
                    if nodecnt == ntotal:
                        self.drawline(str(cd), "hline{0}".format(path_num),
                                      self.svg.get_current_layer(), sstr)
                        path_num = path_num + 1
                    xoffset = xoffset + orig_length
                    prev.x = orig_ex
                    prev.y = orig_ey
                else:
                    prev.x = orig_sx
                    prev.y = orig_sy
                last_letter = ptoken.letter