예제 #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
예제 #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
예제 #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
예제 #5
0
    def test_circle_segment(self):

        # basic circle segment
        c = cf.circle_segment(pi * 0.9)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        # test evaluation at 25 points for radius=1
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 1.0)  # check radius=1

        # radius 7 circle segment
        c = cf.circle_segment(pi * 1.87, 7)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        # test evaluation at 25 points for radius=7
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 7.0)  # check radius=7

        # negative theta
        c = cf.circle_segment(-pi / 2)
        self.assertEqual(c.rational, True)
        self.assertTrue(np.allclose(c(0), [1, 0]))
        self.assertTrue(np.allclose(c(-pi / 4), [1 / sqrt(2), -1 / sqrt(2)]))
        self.assertTrue(np.allclose(c(-pi / 2), [0, -1]))

        # boundary case with one knot span circle segment
        c = cf.circle_segment(2 * pi / 3)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        self.assertEqual(len(c.knots(0)), 2)
        self.assertFalse(c.periodic(0))
        # test evaluation at 25 points for radius=1
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 1.0)  # check radius=1

        # boundary case with full circle
        c = cf.circle_segment(2 * pi)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        self.assertEqual(len(c.knots(0)), 5)
        self.assertTrue(c.periodic(0))
        # test evaluation at 25 points for radius=1
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 1.0)  # check radius=1

        # test errors and exceptions
        with self.assertRaises(ValueError):
            c = cf.circle_segment(3 * pi)  # outside domain
        with self.assertRaises(ValueError):
            c = cf.circle_segment(-3 * pi)  # outside domain
        with self.assertRaises(ValueError):
            c = cf.circle_segment(pi, -2)  # negative radius
예제 #6
0
    def test_circle_segment(self):

        # basic circle segment
        c = CurveFactory.circle_segment(pi * 0.9)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        # test evaluation at 25 points for radius=1
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 1.0)  # check radius=1

        # radius 7 circle segment
        c = CurveFactory.circle_segment(pi * 1.87, 7)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        # test evaluation at 25 points for radius=7
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 7.0)  # check radius=7

        # negative theta
        c = CurveFactory.circle_segment(-pi/2)
        self.assertEqual(c.rational, True)
        self.assertTrue(np.allclose(c(0),     [1,0]))
        self.assertTrue(np.allclose(c(-pi/4), [1/sqrt(2),-1/sqrt(2)]))
        self.assertTrue(np.allclose(c(-pi/2), [0,-1]))

        # boundary case with one knot span circle segment
        c = CurveFactory.circle_segment(2 * pi / 3)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        self.assertEqual(len(c.knots(0)), 2)
        self.assertFalse(c.periodic(0))
        # test evaluation at 25 points for radius=1
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 1.0)  # check radius=1

        # boundary case with full circle
        c = CurveFactory.circle_segment(2 * pi)
        self.assertEqual(c.dimension, 2)
        self.assertEqual(c.rational, True)
        self.assertEqual(len(c.knots(0)), 5)
        self.assertTrue(c.periodic(0))
        # test evaluation at 25 points for radius=1
        t = np.linspace(c.start(0), c.end(0), 25)
        x = c.evaluate(t)
        for pt in np.array(x):
            self.assertAlmostEqual(norm(pt, 2), 1.0)  # check radius=1

        # test errors and exceptions
        with self.assertRaises(ValueError):
            c = CurveFactory.circle_segment(3 * pi)  # outside domain
        with self.assertRaises(ValueError):
            c = CurveFactory.circle_segment(-3 * pi)  # outside domain
        with self.assertRaises(ValueError):
            c = CurveFactory.circle_segment(pi, -2)  # negative radius
예제 #7
0
def thingy(radius, elements, out):
    right = cf.circle_segment(np.pi / 2)
    right.rotate(-np.pi / 4).translate((radius - 1, 0, 0))

    left = right.clone().rotate(np.pi)
    right.reverse()

    thingy = sf.edge_curves(left, right)
    thingy.raise_order(0, 1)
    thingy.refine(*[e - 1 for e in elements])

    with G2(out + '.g2') as f:
        f.write([thingy])
예제 #8
0
def sphere(r=1, center=(0,0,0)):
    """sphere([r=1])

    Create a spherical shell.

    :param float r: Radius
    :param point-like center: Local origin of the sphere
    :return: The spherical shell
    :rtype: Surface
    """
    circle = CurveFactory.circle_segment(pi, r)
    circle.rotate(-pi / 2)
    circle.rotate(pi / 2, (1, 0, 0))  # flip up into xz-plane
    return revolve(circle) + center
예제 #9
0
def sphere(r=1, center=(0, 0, 0), zaxis=(0, 0, 1), xaxis=(1, 0, 0)):
    """  Create a spherical shell.

    :param float r: Radius
    :param array-like center: Local origin of the sphere
    :param array-like zaxis: direction of the north/south pole of the parametrization
    :param array-like xaxis: direction of the longitudal sem
    :return: The spherical shell
    :rtype: Surface
    """
    circle = CurveFactory.circle_segment(pi, r)
    circle.rotate(-pi / 2)
    circle.rotate(pi / 2, (1, 0, 0))  # flip up into xz-plane
    result = revolve(circle)

    result.rotate(rotate_local_x_axis(xaxis, zaxis))
    return flip_and_move_plane_geometry(result, center, zaxis)
예제 #10
0
def revolve(curve, theta=2 * pi, axis=[0,0,1]):
    """revolve(curve, [theta=2pi], [axis=[0,0,1]])

    Revolve a surface by sweeping a curve in a rotational fashion around the
    *z* axis.

    :param Curve curve: Curve to revolve
    :param float theta: Angle to revolve, in radians
    :param vector-like axis: Axis of rotation
    :return: The revolved surface
    :rtype: Surface
    """
    curve = curve.clone()  # clone input curve, throw away input reference
    curve.set_dimension(3)  # add z-components (if not already present)
    curve.force_rational()  # add weight (if not already present)

    # align axis with the z-axis
    normal_theta = atan2(axis[1], axis[0])
    normal_phi   = atan2(sqrt(axis[0]**2 + axis[1]**2), axis[2])
    curve.rotate(-normal_theta, [0,0,1])
    curve.rotate(-normal_phi,   [0,1,0])

    circle_seg = CurveFactory.circle_segment(theta)

    n = len(curve)      # number of control points of the curve
    m = len(circle_seg) # number of control points of the sweep
    cp = np.zeros((m * n, 4))

    # loop around the circle and set control points by the traditional 9-point
    # circle curve with weights 1/sqrt(2), only here C0-periodic, so 8 points
    dt = 0
    t  = 0
    for i in range(m):
        x,y,w = circle_seg[i]
        dt  = atan2(y,x) - t
        t  += dt
        curve.rotate(dt)
        cp[i * n:(i + 1) * n, :]  = curve[:]
        cp[i * n:(i + 1) * n, 2] *= w
        cp[i * n:(i + 1) * n, 3] *= w
    result = Surface(curve.bases[0], circle_seg.bases[0], cp, True)
    # rotate it back again
    result.rotate(normal_phi,   [0,1,0])
    result.rotate(normal_theta, [0,0,1])
    return result
예제 #11
0
def revolve(curve, theta=2 * pi, axis=(0, 0, 1)):
    """  Revolve a surface by sweeping a curve in a rotational fashion around
    the *z* axis.

    :param Curve curve: Curve to revolve
    :param float theta: Angle to revolve, in radians
    :param array-like axis: Axis of rotation
    :return: The revolved surface
    :rtype: Surface
    """
    curve = curve.clone()  # clone input curve, throw away input reference
    curve.set_dimension(3)  # add z-components (if not already present)
    curve.force_rational()  # add weight (if not already present)

    # align axis with the z-axis
    normal_theta = atan2(axis[1], axis[0])
    normal_phi = atan2(sqrt(axis[0]**2 + axis[1]**2), axis[2])
    curve.rotate(-normal_theta, [0, 0, 1])
    curve.rotate(-normal_phi, [0, 1, 0])

    circle_seg = CurveFactory.circle_segment(theta)

    n = len(curve)  # number of control points of the curve
    m = len(circle_seg)  # number of control points of the sweep
    cp = np.zeros((m * n, 4))

    # loop around the circle and set control points by the traditional 9-point
    # circle curve with weights 1/sqrt(2), only here C0-periodic, so 8 points
    dt = 0
    t = 0
    for i in range(m):
        x, y, w = circle_seg[i]
        dt = atan2(y, x) - t
        t += dt
        curve.rotate(dt)
        cp[i * n:(i + 1) * n, :] = curve[:]
        cp[i * n:(i + 1) * n, 2] *= w
        cp[i * n:(i + 1) * n, 3] *= w
    result = Surface(curve.bases[0], circle_seg.bases[0], cp, True)
    # rotate it back again
    result.rotate(normal_phi, [0, 1, 0])
    result.rotate(normal_theta, [0, 0, 1])
    return result
예제 #12
0
def revolve(surf, theta=2 * pi, axis=(0, 0, 1)):
    """  Revolve a volume by sweeping a surface in a rotational fashion around
    an axis.

    :param Surface surf: Surface to revolve
    :param float theta: Angle to revolve, in radians
    :param array-like axis: Axis of rotation
    :return: The revolved surface
    :rtype: Volume
    """
    surf = surf.clone()  # clone input surface, throw away old reference
    surf.set_dimension(3)  # add z-components (if not already present)
    surf.force_rational()  # add weight (if not already present)

    # align axis with the z-axis
    normal_theta = atan2(axis[1], axis[0])
    normal_phi = atan2(sqrt(axis[0]**2 + axis[1]**2), axis[2])
    surf.rotate(-normal_theta, [0, 0, 1])
    surf.rotate(-normal_phi, [0, 1, 0])

    path = CurveFactory.circle_segment(theta=theta)
    n = len(surf)  # number of control points of the surface
    m = len(path)  # number of control points of the sweep

    cp = np.zeros((m * n, 4))

    dt = np.sign(theta) * (path.knots(0)[1] - path.knots(0)[0]) / 2.0
    for i in range(m):
        weight = path[i, -1]
        cp[i * n:(i + 1) * n, :] = np.reshape(
            surf.controlpoints.transpose(1, 0, 2), (n, 4))
        cp[i * n:(i + 1) * n, 2] *= weight
        cp[i * n:(i + 1) * n, 3] *= weight
        surf.rotate(dt)
    result = Volume(surf.bases[0], surf.bases[1], path.bases[0], cp, True)
    # rotate it back again
    result.rotate(normal_phi, [0, 1, 0])
    result.rotate(normal_theta, [0, 0, 1])
    return result
예제 #13
0
def revolve(surf, theta=2 * pi, axis=(0,0,1)):
    """  Revolve a volume by sweeping a surface in a rotational fashion around
    an axis.

    :param Surface surf: Surface to revolve
    :param float theta: Angle to revolve, in radians
    :param array-like axis: Axis of rotation
    :return: The revolved surface
    :rtype: Volume
    """
    surf = surf.clone()  # clone input surface, throw away old reference
    surf.set_dimension(3)  # add z-components (if not already present)
    surf.force_rational()  # add weight (if not already present)

    # align axis with the z-axis
    normal_theta = atan2(axis[1], axis[0])
    normal_phi   = atan2(sqrt(axis[0]**2 + axis[1]**2), axis[2])
    surf.rotate(-normal_theta, [0,0,1])
    surf.rotate(-normal_phi,   [0,1,0])

    path = CurveFactory.circle_segment(theta=theta)
    n = len(surf)  # number of control points of the surface
    m = len(path)  # number of control points of the sweep

    cp = np.zeros((m * n, 4))

    dt = np.sign(theta)*(path.knots(0)[1] - path.knots(0)[0]) / 2.0
    for i in range(m):
        weight = path[i,-1]
        cp[i * n:(i + 1) * n, :] = np.reshape(surf.controlpoints.transpose(1, 0, 2), (n, 4))
        cp[i * n:(i + 1) * n, 2] *= weight
        cp[i * n:(i + 1) * n, 3] *= weight
        surf.rotate(dt)
    result = Volume(surf.bases[0], surf.bases[1], path.bases[0], cp, True)
    # rotate it back again
    result.rotate(normal_phi,   [0,1,0])
    result.rotate(normal_theta, [0,0,1])
    return result
예제 #14
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
예제 #15
0
# Institute: Norwegian University of Science and Technology (NTNU)
# Date:      March 2016
#

from sys import path
path.append('../')
from splipy import *
import splipy.curve_factory as curves
import splipy.surface_factory as surfaces
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from math import pi, cos, sin

# create the three sides of the triangle, each consisting of a circle segment
c1 = curves.circle_segment(pi/3)
c2 = c1.clone().rotate(2*pi/3) + [1,0]
c3 = c1.clone().rotate(4*pi/3) + [cos(pi/3), sin(pi/3)]

# merge the three circles into one, and center it at the origin
c = c1.append(c2).append(c3)
c -= c.center()

# plot the reuleaux triangle
t = np.linspace(c.start(0), c.end(0), 151) # 151 parametric evaluation points
x = c(t)                                   # evaluate (x,y)-coordinates
plt.plot(x[:,0], x[:,1])
plt.axis('equal')
plt.show()

# split the triangle in two, and align this with the y-axis
예제 #16
0
import splipy.curve_factory as CurveFactory
import splipy.surface_factory as SurfaceFactory
from splipy.io import G2
from math import sqrt, sin, pi

beta = 0.1
R = 2540
l = 508
w = 2*R*sin(beta)
y0 = -sqrt(R*R-0.25*w*w)
arch = CurveFactory.circle_segment(2*beta,R,[0,0,1])
arch.rotate(pi/2-beta)
arch.translate([0,y0,0])
shell = SurfaceFactory.extrude(arch,[0,0,l])
print(shell)

with G2('shallow_arch.g2') as output:
    output.write(shell)
예제 #17
0
# Institute: Norwegian University of Science and Technology (NTNU)
# Date:      March 2016
#

from sys import path
path.append('../')
from splipy import *
import splipy.curve_factory as curves
import splipy.surface_factory as surfaces
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from math import pi, cos, sin

# create the three sides of the triangle, each consisting of a circle segment
c1 = curves.circle_segment(pi / 3)
c2 = c1.clone().rotate(2 * pi / 3) + [1, 0]
c3 = c1.clone().rotate(4 * pi / 3) + [cos(pi / 3), sin(pi / 3)]

# merge the three circles into one, and center it at the origin
c = c1.append(c2).append(c3)
c -= c.center()

# plot the reuleaux triangle
t = np.linspace(c.start(0), c.end(0), 151)  # 151 parametric evaluation points
x = c(t)  # evaluate (x,y)-coordinates
plt.plot(x[:, 0], x[:, 1])
plt.axis('equal')
plt.show()

# split the triangle in two, and align this with the y-axis
예제 #18
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