예제 #1
0
 def test_length(self):
     crv = Curve()
     self.assertAlmostEqual(crv.length(), 1.0)
     crv = Curve(BSplineBasis(2, [-1,-1,1,2,3,3]), [[0,0,0], [1,0,0], [1,0,3],[1,10,3]])
     self.assertAlmostEqual(crv.length(), 14.0)
예제 #2
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
예제 #3
0
파일: curve_test.py 프로젝트: SINTEF/Splipy
 def test_length(self):
     crv = Curve()
     self.assertAlmostEqual(crv.length(), 1.0)
     crv = Curve(BSplineBasis(2, [-1, -1, 1, 2, 3, 3]),
                 [[0, 0, 0], [1, 0, 0], [1, 0, 3], [1, 10, 3]])
     self.assertAlmostEqual(crv.length(), 14.0)
예제 #4
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