Example #1
0
    def test_edge_curves(self):
        # create an arrow-like 2D geometry with the pointy end at (-1,1) towards up and left
        # mixes rational and non-rational curves with different parametrization spaces
        c1 = CurveFactory.circle_segment(pi / 2)
        c2 = Curve(BSplineBasis(2, [0, 0, 1, 2, 2]), [[0, 1], [-1, 1], [-1, 0]])
        c3 = CurveFactory.circle_segment(pi / 2)
        c3.rotate(pi)
        c4 = Curve(BSplineBasis(2), [[0, -1], [1, 0]])

        surf = SurfaceFactory.edge_curves(c1, c2, c3, c4)

        # srf spits out parametric space (0,1)^2, so we sync these up to input curves
        c3.reverse()
        c4.reverse()
        c1.reparam()
        c2.reparam()
        c3.reparam()
        c4.reparam()

        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 0)[0], c1(u)[0])  # x-coord, bottom crv
            self.assertAlmostEqual(surf(u, 0)[1], c1(u)[1])  # y-coord, bottom crv
        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 1)[0], c3(u)[0])  # x-coord, top crv
            self.assertAlmostEqual(surf(u, 1)[1], c3(u)[1])  # y-coord, top crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(0, v)[0], c4(v)[0])  # x-coord, left crv
            self.assertAlmostEqual(surf(0, v)[1], c4(v)[1])  # y-coord, left crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(1, v)[0], c2(v)[0])  # x-coord, right crv
            self.assertAlmostEqual(surf(1, v)[1], c2(v)[1])  # y-coord, right crv
Example #2
0
    def test_edge_curves(self):
        # create an arrow-like 2D geometry with the pointy end at (-1,1) towards up and left
        # mixes rational and non-rational curves with different parametrization spaces
        c1 = cf.circle_segment(pi / 2)
        c2 = Curve(BSplineBasis(2, [0, 0, 1, 2, 2]),
                   [[0, 1], [-1, 1], [-1, 0]])
        c3 = cf.circle_segment(pi / 2)
        c3.rotate(pi)
        c4 = Curve(BSplineBasis(2), [[0, -1], [1, 0]])

        surf = sf.edge_curves(c1, c2, c3, c4)

        # srf spits out parametric space (0,1)^2, so we sync these up to input curves
        c3.reverse()
        c4.reverse()
        c1.reparam()
        c2.reparam()
        c3.reparam()
        c4.reparam()

        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 0)[0],
                                   c1(u)[0])  # x-coord, bottom crv
            self.assertAlmostEqual(surf(u, 0)[1],
                                   c1(u)[1])  # y-coord, bottom crv
        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 1)[0], c3(u)[0])  # x-coord, top crv
            self.assertAlmostEqual(surf(u, 1)[1], c3(u)[1])  # y-coord, top crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(0, v)[0],
                                   c4(v)[0])  # x-coord, left crv
            self.assertAlmostEqual(surf(0, v)[1],
                                   c4(v)[1])  # y-coord, left crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(1, v)[0],
                                   c2(v)[0])  # x-coord, right crv
            self.assertAlmostEqual(surf(1, v)[1],
                                   c2(v)[1])  # y-coord, right crv

        # add a case where opposing sites have mis-matching rationality
        crvs = Surface().edges()  # returned in order umin, umax, vmin, vmax
        crvs[0].force_rational()
        crvs[1].reverse()
        crvs[2].reverse()
        # input curves should be clockwise oriented closed loop
        srf = sf.edge_curves(crvs[0], crvs[3], crvs[1], crvs[2])
        crvs[1].reverse()
        u = np.linspace(0, 1, 7)
        self.assertTrue(np.allclose(srf(u, 0).reshape((7, 2)), crvs[0](u)))
        self.assertTrue(np.allclose(srf(u, 1).reshape((7, 2)), crvs[1](u)))

        # test self-organizing curve ordering when they are not sequential
        srf = sf.edge_curves(crvs[0], crvs[2].reverse(), crvs[3], crvs[1])
        u = np.linspace(0, 1, 7)
        self.assertTrue(np.allclose(srf(u, 0).reshape((7, 2)), crvs[0](u)))
        self.assertTrue(np.allclose(srf(u, 1).reshape((7, 2)), crvs[1](u)))

        # test error handling
        with self.assertRaises(ValueError):
            srf = sf.edge_curves(crvs + (Curve(), ))  # 5 input curves
Example #3
0
    def test_edge_curves_elasticity(self):
        # create an arrow-like 2D geometry with the pointy end at (-1,1) towards up and left
        # rebuild to avoid rational representations
        c1 = CurveFactory.circle_segment(pi / 2).rebuild(3,11)
        c2 = Curve(BSplineBasis(2, [0, 0, 1, 2, 2]), [[0, 1], [-1, 1], [-1, 0]])
        c3 = CurveFactory.circle_segment(pi / 2).rebuild(3,11)
        c3.rotate(pi)
        c4 = Curve(BSplineBasis(2), [[0, -1], [1, 0]]).rebuild(3,10)
        c4 = c4.rebuild(4,11)

        surf = SurfaceFactory.edge_curves([c1, c2, c3, c4], type='elasticity')

        # check right dimensions of output
        self.assertEqual(surf.shape[0], 11) # 11 controlpoints in the circle segment
        self.assertEqual(surf.shape[1], 13) # 11 controlpoints in c4, +2 for C0-knot in c1
        self.assertEqual(surf.order(0), 3)
        self.assertEqual(surf.order(1), 4)

        # check that c1 edge conforms to surface edge
        u = np.linspace(0,1,7)
        c1.reparam()
        pts_surf = surf(u,0.0)
        pts_c1   = c1(u)
        for (xs,xc) in zip(pts_surf[:,0,:], pts_c1):
            self.assertTrue(np.allclose(xs, xc))

        # check that c2 edge conforms to surface edge
        v = np.linspace(0,1,7)
        c2.reparam()
        pts_surf = surf(1.0,v)
        pts_c2   = c2(v)
        for (xs,xc) in zip(pts_surf[:,0,:], pts_c2):
            self.assertTrue(np.allclose(xs, xc))
    def test_edge_curves(self):
        # create an arrow-like 2D geometry with the pointy end at (-1,1) towards up and left
        # mixes rational and non-rational curves with different parametrization spaces
        c1 = CurveFactory.circle_segment(pi / 2)
        c2 = Curve(BSplineBasis(2, [0, 0, 1, 2, 2]), [[0, 1], [-1, 1], [-1, 0]])
        c3 = CurveFactory.circle_segment(pi / 2)
        c3.rotate(pi)
        c4 = Curve(BSplineBasis(2), [[0, -1], [1, 0]])

        surf = SurfaceFactory.edge_curves(c1, c2, c3, c4)

        # srf spits out parametric space (0,1)^2, so we sync these up to input curves
        c3.reverse()
        c4.reverse()
        c1.reparam()
        c2.reparam()
        c3.reparam()
        c4.reparam()

        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 0)[0], c1(u)[0])  # x-coord, bottom crv
            self.assertAlmostEqual(surf(u, 0)[1], c1(u)[1])  # y-coord, bottom crv
        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 1)[0], c3(u)[0])  # x-coord, top crv
            self.assertAlmostEqual(surf(u, 1)[1], c3(u)[1])  # y-coord, top crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(0, v)[0], c4(v)[0])  # x-coord, left crv
            self.assertAlmostEqual(surf(0, v)[1], c4(v)[1])  # y-coord, left crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(1, v)[0], c2(v)[0])  # x-coord, right crv
            self.assertAlmostEqual(surf(1, v)[1], c2(v)[1])  # y-coord, right crv

        # add a case where opposing sites have mis-matching rationality
        crvs = Surface().edges() # returned in order umin, umax, vmin, vmax
        crvs[0].force_rational()
        crvs[1].reverse()
        crvs[2].reverse()
        # input curves should be clockwise oriented closed loop
        srf = SurfaceFactory.edge_curves(crvs[0], crvs[3], crvs[1], crvs[2])
        crvs[1].reverse()
        u = np.linspace(0,1,7)
        self.assertTrue(np.allclose(srf(u,0).reshape((7,2)), crvs[0](u)))
        self.assertTrue(np.allclose(srf(u,1).reshape((7,2)), crvs[1](u)))

        # test self-organizing curve ordering when they are not sequential
        srf = SurfaceFactory.edge_curves(crvs[0], crvs[2].reverse(), crvs[3], crvs[1])
        u = np.linspace(0,1,7)
        self.assertTrue(np.allclose(srf(u,0).reshape((7,2)), crvs[0](u)))
        self.assertTrue(np.allclose(srf(u,1).reshape((7,2)), crvs[1](u)))

        # test error handling
        with self.assertRaises(ValueError):
            srf = SurfaceFactory.edge_curves(crvs + (Curve(),)) # 5 input curves
Example #5
0
    def test_reparam(self):
        # non-uniform knot vector of a squiggly quadratic n=4 curve
        controlpoints = [[0, 0, 0], [1, 1, 0], [2, -1, 0], [3, 0, 0]]
        crv = Curve(BSplineBasis(3, [0, 0, 0, 1.32, 3, 3, 3]), controlpoints)

        # get some info on the initial curve
        knots1 = crv.knots(0)
        evaluation_point1 = crv(1.20)
        self.assertEqual(knots1[0], 0)
        self.assertEqual(knots1[-1], 3)

        # reparametrize
        crv.reparam((6.0, 9.0))

        # get some info on the reparametrized curve
        knots2 = crv.knots(0)
        evaluation_point2 = crv(7.20)
        self.assertEqual(knots2[0], 6)
        self.assertEqual(knots2[-1], 9)

        # ensure that curve has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])

        # normalize, i.e. set domain to [0,1]
        crv.reparam()

        # get some info on the normalized curve
        knots3 = crv.knots(0)
        evaluation_point3 = crv(0.40)
        self.assertEqual(knots3[0], 0)
        self.assertEqual(knots3[-1], 1)

        # ensure that curve has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point3[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point3[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point3[2])

        # test errors and exceptions
        with self.assertRaises(ValueError):
            crv.reparam((9, 3))
        with self.assertRaises(TypeError):
            crv.reparam(("one", "two"))
Example #6
0
    def test_reparam(self):
        # non-uniform knot vector of a squiggly quadratic n=4 curve
        controlpoints = [[0, 0, 0], [1, 1, 0], [2, -1, 0], [3, 0, 0]]
        crv = Curve(BSplineBasis(3, [0, 0, 0, 1.32, 3, 3, 3]), controlpoints)

        # get some info on the initial curve
        knots1 = crv.knots(0)
        evaluation_point1 = crv(1.20)
        self.assertEqual(knots1[0], 0)
        self.assertEqual(knots1[-1], 3)

        # reparametrize
        crv.reparam((6.0, 9.0))

        # get some info on the reparametrized curve
        knots2 = crv.knots(0)
        evaluation_point2 = crv(7.20)
        self.assertEqual(knots2[0], 6)
        self.assertEqual(knots2[-1], 9)

        # ensure that curve has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])

        # normalize, i.e. set domain to [0,1]
        crv.reparam()

        # get some info on the normalized curve
        knots3 = crv.knots(0)
        evaluation_point3 = crv(0.40)
        self.assertEqual(knots3[0], 0)
        self.assertEqual(knots3[-1], 1)

        # ensure that curve has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point3[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point3[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point3[2])

        # test errors and exceptions
        with self.assertRaises(ValueError):
            crv.reparam((9, 3))
        with self.assertRaises(TypeError):
            crv.reparam(("one", "two"))
Example #7
0
    def curves_from_path(self, path):
        # see https://www.w3schools.com/graphics/svg_path.asp for documentation
        # and also https://www.w3.org/TR/SVG/paths.html

        # figure out the largest polynomial order of this path
        if re.search('[cCsS]', path):
            order = 4
        elif re.search('[qQtTaA]', path):
            order = 3
        else:
            order = 2
        last_curve = None
        result = []

        # each 'piece' is an operator (M,C,Q,L etc) and accomponying list of argument points
        for piece in re.findall('[a-zA-Z][^a-zA-Z]*', path):

            # if not single-letter command (i.e. 'z')
            if len(piece) > 1:
                # points is a (string-)list of (x,y)-coordinates for the given operator
                points = re.findall('-?\d+\.?\d*', piece[1:])

                if piece[0].lower() != 'a' and piece[0].lower(
                ) != 'v' and piece[0].lower() != 'h':
                    # convert string-list to a list of numpy arrays (of size 2)
                    np_pts = np.reshape(
                        np.array(points).astype('float'),
                        (int(len(points) / 2), 2))

            if piece[0] == 'm' or piece[0] == 'M':
                # I really hope it always start with a move command (think it does)
                startpoint = np_pts[0]
                if len(np_pts) > 1:
                    if piece[0] == 'M':
                        knot = [0] + list(range(
                            len(np_pts))) + [len(np_pts) - 1]
                        curve_piece = Curve(BSplineBasis(2, knot), np_pts)
                    elif piece[0] == 'm':
                        knot = [0] + list(range(
                            len(np_pts))) + [len(np_pts) - 1]
                        controlpoints = [startpoint]
                        for cp in np_pts[1:]:
                            controlpoints.append(cp + controlpoints[-1])
                        curve_piece = Curve(BSplineBasis(2, knot),
                                            controlpoints)
                else:
                    continue
            elif piece[0] == 'c':
                # cubic spline, relatively positioned
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts) / 3) + 1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[int(
                        (len(controlpoints) - 1) / 3) * 3]
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 'C':
                # cubic spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts) / 3) + 1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 's':
                # smooth cubic spline, relative position
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts) / 2) + 1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                x0 = np.array(last_curve[-1])
                xn1 = np.array(last_curve[-2])
                controlpoints.append(2 * x0 - xn1)
                startpoint = controlpoints[-1]
                for i, cp in enumerate(np_pts):
                    if i % 2 == 0 and i > 0:
                        startpoint = controlpoints[-1]
                        controlpoints.append(2 * controlpoints[-1] -
                                             controlpoints[-2])
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 'S':
                # smooth cubic spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts) / 2) + 1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                x0 = np.array(last_curve[-1])
                xn1 = np.array(last_curve[-2])
                controlpoints.append(2 * x0 - xn1)
                for i, cp in enumerate(np_pts):
                    if i % 2 == 0 and i > 0:
                        controlpoints.append(2 * controlpoints[-1] -
                                             controlpoints[-2])
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 'q':
                # quadratic spline, relatively positioned
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts) / 2) + 1)) * 2
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[int(
                        (len(controlpoints) - 1) / 2) * 2]
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(3, knot), controlpoints)
            elif piece[0] == 'Q':
                # quadratic spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) / 2 + 1)) * 2
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(3, knot), controlpoints)
            elif piece[0] == 'l':
                # linear spline, relatively positioned
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) + 1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[-1]
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'L':
                # linear spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) + 1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'h':
                # horizontal piece, relatively positioned
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) + 1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[-1]
                    controlpoints.append(np.array([cp, 0]) + startpoint)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'H':
                # horizontal piece, absolute position
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) + 1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append([cp, startpoint[1]])
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'v':
                # vertical piece, relatively positioned
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) + 1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[-1]
                    controlpoints.append(np.array([0, cp]) + startpoint)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'V':
                # vertical piece, absolute position
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts) + 1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append([startpoint[0], cp])
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'A' or piece[0] == 'a':
                np_pts = np.reshape(
                    np.array(points).astype('float'), (int(len(points))))
                rx = float(points[0])
                ry = float(points[1])
                x_axis_rotation = float(points[2])
                large_arc_flag = (points[3] != '0')
                sweep_flag = (points[4] != '0')
                xend = np.array([float(points[5]), float(points[6])])
                if piece[0] == 'a':
                    xend += startpoint

                R = np.array(
                    [[np.cos(x_axis_rotation),
                      np.sin(x_axis_rotation)],
                     [-np.sin(x_axis_rotation),
                      np.cos(x_axis_rotation)]])
                xp = np.linalg.solve(R, (startpoint - xend) / 2)
                if sweep_flag == large_arc_flag:
                    cprime = -(np.sqrt(
                        abs(rx**2 * ry**2 - rx**2 * xp[1]**2 -
                            ry**2 * xp[0]**2) /
                        (rx**2 * xp[1]**2 + ry**2 * xp[0]**2)) *
                               np.array([rx * xp[1] / ry, -ry * xp[0] / rx]))
                else:
                    cprime = +(np.sqrt(
                        abs(rx**2 * ry**2 - rx**2 * xp[1]**2 -
                            ry**2 * xp[0]**2) /
                        (rx**2 * xp[1]**2 + ry**2 * xp[0]**2)) *
                               np.array([rx * xp[1] / ry, -ry * xp[0] / rx]))
                center = np.linalg.solve(R.T, cprime) + (startpoint + xend) / 2

                def arccos(vec1, vec2):
                    return (np.sign(vec1[0] * vec2[1] - vec1[1] * vec2[0]) *
                            np.arccos(
                                vec1.dot(vec2) / np.linalg.norm(vec1) /
                                np.linalg.norm(vec2)))

                tmp1 = np.divide(xp - cprime, [rx, ry])
                tmp2 = np.divide(-xp - cprime, [rx, ry])
                theta1 = arccos(np.array([1, 0]), tmp1)
                delta_t = arccos(tmp1, tmp2) % (2 * np.pi)
                if not sweep_flag and delta_t > 0:
                    delta_t -= 2 * np.pi
                elif sweep_flag and delta_t < 0:
                    delta_t += 2 * np.pi
                curve_piece = (curve_factory.circle_segment(delta_t) *
                               [rx, ry]).rotate(theta1) + center
                # curve_piece = curve_factory.circle_segment(delta_t)

            elif piece[0] == 'z' or piece[0] == 'Z':
                # periodic curve
                # curve_piece = Curve(BSplineBasis(2), [startpoint, last_curve[0]])
                # curve_piece.reparam([0, curve_piece.length()])
                # last_curve.append(curve_piece).make_periodic(0)
                last_curve.make_periodic(0)
                result.append(last_curve)
                last_curve = None
                continue
            else:
                raise RuntimeError('Unknown path parameter:' + piece)

            if (curve_piece.length() > state.controlpoint_absolute_tolerance):
                curve_piece.reparam([0, curve_piece.length()])
                if last_curve is None:
                    last_curve = curve_piece
                else:
                    last_curve.append(curve_piece)
            startpoint = last_curve[-1, :
                                    2]  # disregard rational weight (if any)

        if last_curve is not None:
            result.append(last_curve)
        return result
Example #8
0
    def curves_from_path(self, path):
        # see https://www.w3schools.com/graphics/svg_path.asp for documentation
        # and also https://www.w3.org/TR/SVG/paths.html

        # figure out the largest polynomial order of this path
        if re.search('[cCsS]', path):
            order = 4
        elif re.search('[qQtTaA]', path):
            order = 3
        else:
            order = 2
        last_curve = None
        result = []

        # each 'piece' is an operator (M,C,Q,L etc) and accomponying list of argument points
        for piece in re.findall('[a-zA-Z][^a-zA-Z]*', path):

            # if not single-letter command (i.e. 'z')
            if len(piece)>1:
                # points is a (string-)list of (x,y)-coordinates for the given operator
                points = re.findall('-?\d+\.?\d*', piece[1:])

                if piece[0].lower() != 'a' and piece[0].lower() != 'v' and piece[0].lower() != 'h':
                    # convert string-list to a list of numpy arrays (of size 2)
                    np_pts = np.reshape(np.array(points).astype('float'), (int(len(points)/2),2))

            if piece[0] == 'm' or piece[0] == 'M':
                # I really hope it always start with a move command (think it does)
                startpoint = np_pts[0]
                if len(np_pts) > 1:
                    if piece[0] == 'M':
                        knot = [0] + list(range(len(np_pts))) + [len(np_pts)-1]
                        curve_piece = Curve(BSplineBasis(2, knot), np_pts)
                    elif piece[0] == 'm':
                        knot = [0] + list(range(len(np_pts))) + [len(np_pts)-1]
                        controlpoints = [startpoint]
                        for cp in np_pts[1:]:
                            controlpoints.append(cp + controlpoints[-1])
                        curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
                else:
                    continue
            elif piece[0] == 'c':
                # cubic spline, relatively positioned
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts)/3)+1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[int((len(controlpoints)-1)/3)*3]
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 'C':
                # cubic spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts)/3)+1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 's':
                # smooth cubic spline, relative position
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts)/2)+1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                x0  = np.array(last_curve[-1])
                xn1 = np.array(last_curve[-2])
                controlpoints.append(2*x0 -xn1)
                startpoint = controlpoints[-1]
                for i, cp in enumerate(np_pts):
                    if i % 2 == 0 and i>0:
                        startpoint = controlpoints[-1]
                        controlpoints.append(2*controlpoints[-1] - controlpoints[-2])
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 'S':
                # smooth cubic spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts)/2)+1)) * 3
                knot += [knot[0], knot[-1]]
                knot.sort()
                x0  = np.array(last_curve[-1])
                xn1 = np.array(last_curve[-2])
                controlpoints.append(2*x0 -xn1)
                for i,cp in enumerate(np_pts):
                    if i % 2 == 0 and i>0:
                        controlpoints.append(2*controlpoints[-1] - controlpoints[-2])
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(4, knot), controlpoints)
            elif piece[0] == 'q':
                # quadratic spline, relatively positioned
                controlpoints = [startpoint]
                knot = list(range(int(len(np_pts)/2)+1)) * 2
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[int((len(controlpoints)-1)/2)*2]
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(3, knot), controlpoints)
            elif piece[0] == 'Q':
                # quadratic spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)/2+1)) * 2
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(3, knot), controlpoints)
            elif piece[0] == 'l':
                # linear spline, relatively positioned
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)+1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[-1]
                    controlpoints.append(cp + startpoint)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'L':
                # linear spline, absolute position
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)+1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append(cp)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'h':
                # horizontal piece, relatively positioned
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)+1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[-1]
                    controlpoints.append(np.array([cp, 0]) + startpoint)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'H':
                # horizontal piece, absolute position
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)+1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append([cp, startpoint[1]])
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'v':
                # vertical piece, relatively positioned
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)+1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    startpoint = controlpoints[-1]
                    controlpoints.append(np.array([0, cp]) + startpoint)
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'V':
                # vertical piece, absolute position
                np_pts = np.array(points).astype('float')
                controlpoints = [startpoint]
                knot = list(range(len(np_pts)+1))
                knot += [knot[0], knot[-1]]
                knot.sort()
                for cp in np_pts:
                    controlpoints.append([startpoint[0], cp])
                curve_piece = Curve(BSplineBasis(2, knot), controlpoints)
            elif piece[0] == 'A' or piece[0] == 'a':
                np_pts = np.reshape(np.array(points).astype('float'), (int(len(points))))
                rx              = float(points[0])
                ry              = float(points[1])
                x_axis_rotation = float(points[2])
                large_arc_flag  = (points[3] != '0')
                sweep_flag      = (points[4] != '0')
                xend            = np.array([float(points[5]), float(points[6]) ])
                if piece[0] == 'a':
                    xend += startpoint

                R = np.array([[ np.cos(x_axis_rotation), np.sin(x_axis_rotation)],
                              [-np.sin(x_axis_rotation), np.cos(x_axis_rotation)]])
                xp = np.linalg.solve(R, (startpoint - xend)/2)
                if sweep_flag == large_arc_flag:
                    cprime = -(np.sqrt(abs(rx**2*ry**2 - rx**2*xp[1]**2 - ry**2*xp[0]**2) /
                                       (rx**2*xp[1]**2 + ry**2*xp[0]**2)) *
                                       np.array([rx*xp[1]/ry, -ry*xp[0]/rx]))
                else:
                    cprime = +(np.sqrt(abs(rx**2*ry**2 - rx**2*xp[1]**2 - ry**2*xp[0]**2) /
                                       (rx**2*xp[1]**2 + ry**2*xp[0]**2)) *
                                       np.array([rx*xp[1]/ry, -ry*xp[0]/rx]))
                center = np.linalg.solve(R.T, cprime) + (startpoint+xend)/2
                def arccos(vec1, vec2):
                    return (np.sign(vec1[0]*vec2[1] - vec1[1]*vec2[0]) *
                            np.arccos(vec1.dot(vec2)/np.linalg.norm(vec1)/np.linalg.norm(vec2)))
                tmp1 = np.divide( xp - cprime, [rx,ry])
                tmp2 = np.divide(-xp - cprime, [rx,ry])
                theta1 = arccos(np.array([1,0]), tmp1)
                delta_t= arccos(tmp1, tmp2) % (2*np.pi)
                if not sweep_flag and delta_t > 0:
                    delta_t -= 2*np.pi
                elif sweep_flag and delta_t < 0:
                    delta_t += 2*np.pi
                curve_piece = (curve_factory.circle_segment(delta_t)*[rx,ry]).rotate(theta1) + center
                # curve_piece = curve_factory.circle_segment(delta_t)

            elif piece[0] == 'z' or piece[0] == 'Z':
                # periodic curve
                # curve_piece = Curve(BSplineBasis(2), [startpoint, last_curve[0]])
                # curve_piece.reparam([0, curve_piece.length()])
                # last_curve.append(curve_piece).make_periodic(0)
                last_curve.make_periodic(0)
                result.append(last_curve)
                last_curve = None
                continue
            else:
                raise RuntimeError('Unknown path parameter:' + piece)

            if(curve_piece.length()>state.controlpoint_absolute_tolerance):
                curve_piece.reparam([0, curve_piece.length()])
                if last_curve is None:
                    last_curve = curve_piece
                else:
                    last_curve.append(curve_piece)
            startpoint = last_curve[-1,:2] # disregard rational weight (if any)

        if last_curve is not None:
            result.append(last_curve)
        return result