Example #1
0
def sphere(r=1, center=(0, 0, 0), type='radial'):
    """  Create a solid sphere

    :param float r: Radius
    :param array-like center: Local origin of the sphere
    :param string type: The type of parametrization ('radial' or 'square')
    :return: A solid ball
    :rtype: Volume
    """
    if type == 'radial':
        shell = SurfaceFactory.sphere(r, center)
        midpoint = shell * 0 + center
        return edge_surfaces(shell, midpoint)
    elif type == 'square':
        # based on the work of James E.Cobb: "Tiling the Sphere with Rational Bezier Patches"
        # University of Utah, July 11, 1988. UUCS-88-009
        b = BSplineBasis(order=5)
        sr2 = sqrt(2)
        sr3 = sqrt(3)
        sr6 = sqrt(6)
        cp = [
            [-4 * (sr3 - 1), 4 * (1 - sr3), 4 * (1 - sr3),
             4 * (3 - sr3)],  # row 0
            [-sr2, sr2 * (sr3 - 4), sr2 * (sr3 - 4), sr2 * (3 * sr3 - 2)],
            [
                0, 4. / 3 * (1 - 2 * sr3), 4. / 3 * (1 - 2 * sr3),
                4. / 3 * (5 - sr3)
            ],
            [sr2, sr2 * (sr3 - 4), sr2 * (sr3 - 4), sr2 * (3 * sr3 - 2)],
            [4 * (sr3 - 1), 4 * (1 - sr3), 4 * (1 - sr3), 4 * (3 - sr3)],
            [-sr2 * (4 - sr3), -sr2, sr2 * (sr3 - 4),
             sr2 * (3 * sr3 - 2)],  # row 1
            [
                -(3 * sr3 - 2) / 2, (2 - 3 * sr3) / 2, -(sr3 + 6) / 2,
                (sr3 + 6) / 2
            ],
            [0, sr2 * (2 * sr3 - 7) / 3, -5 * sr6 / 3, sr2 * (sr3 + 6) / 3],
            [(3 * sr3 - 2) / 2, (2 - 3 * sr3) / 2, -(sr3 + 6) / 2,
             (sr3 + 6) / 2],
            [sr2 * (4 - sr3), -sr2, sr2 * (sr3 - 4), sr2 * (3 * sr3 - 2)],
            [
                -4. / 3 * (2 * sr3 - 1), 0, 4. / 3 * (1 - 2 * sr3),
                4 * (5 - sr3) / 3
            ],  # row 2
            [-sr2 / 3 * (7 - 2 * sr3), 0, -5 * sr6 / 3, sr2 * (sr3 + 6) / 3],
            [0, 0, 4 * (sr3 - 5) / 3, 4 * (5 * sr3 - 1) / 9],
            [sr2 / 3 * (7 - 2 * sr3), 0, -5 * sr6 / 3, sr2 * (sr3 + 6) / 3],
            [
                4. / 3 * (2 * sr3 - 1), 0, 4. / 3 * (1 - 2 * sr3),
                4 * (5 - sr3) / 3
            ],
            [-sr2 * (4 - sr3), sr2, sr2 * (sr3 - 4),
             sr2 * (3 * sr3 - 2)],  # row 3
            [
                -(3 * sr3 - 2) / 2, -(2 - 3 * sr3) / 2, -(sr3 + 6) / 2,
                (sr3 + 6) / 2
            ],
            [0, -sr2 * (2 * sr3 - 7) / 3, -5 * sr6 / 3, sr2 * (sr3 + 6) / 3],
            [(3 * sr3 - 2) / 2, -(2 - 3 * sr3) / 2, -(sr3 + 6) / 2,
             (sr3 + 6) / 2],
            [sr2 * (4 - sr3), sr2, sr2 * (sr3 - 4), sr2 * (3 * sr3 - 2)],
            [-4 * (sr3 - 1), -4 * (1 - sr3), 4 * (1 - sr3),
             4 * (3 - sr3)],  # row 4
            [-sr2, -sr2 * (sr3 - 4), sr2 * (sr3 - 4), sr2 * (3 * sr3 - 2)],
            [
                0, -4. / 3 * (1 - 2 * sr3), 4. / 3 * (1 - 2 * sr3),
                4. / 3 * (5 - sr3)
            ],
            [sr2, -sr2 * (sr3 - 4), sr2 * (sr3 - 4), sr2 * (3 * sr3 - 2)],
            [4 * (sr3 - 1), -4 * (1 - sr3), 4 * (1 - sr3), 4 * (3 - sr3)]
        ]
        wmin = Surface(b, b, cp, rational=True)
        wmax = wmin.clone().mirror([0, 0, 1])
        vmax = wmin.clone().rotate(pi / 2, [1, 0, 0])
        vmin = vmax.clone().mirror([0, 1, 0])
        umax = vmin.clone().rotate(pi / 2, [0, 0, 1])
        umin = umax.clone().mirror([1, 0, 0])
        # ideally I would like to call edge_surfaces() now, but that function
        # does not work with rational surfaces, so we'll just manually try
        # and add some inner controlpoints
        cp = np.zeros((5, 5, 5, 4))
        cp[:, :, 0, :] = wmin[:, :, :]
        cp[:, :, -1, :] = wmax[:, :, :]
        cp[:, 0, :, :] = vmin[:, :, :]
        cp[:, -1, :, :] = vmax[:, :, :]
        cp[0, :, :, :] = umin[:, :, :]
        cp[-1, :, :, :] = umax[:, :, :]
        inner = np.linspace(-.5, .5, 3)
        Y, X, Z = np.meshgrid(inner, inner, inner)
        cp[1:4, 1:4, 1:4, 0] = X
        cp[1:4, 1:4, 1:4, 1] = Y
        cp[1:4, 1:4, 1:4, 2] = Z
        cp[1:4, 1:4, 1:4, 3] = 1
        ball = Volume(b, b, b, cp, rational=True, raw=True)
        return r * ball + center
    else:
        raise ValueError('invalid type argument')
Example #2
0
def sphere(r=1, center=(0,0,0), type='radial'):
    """  Create a solid sphere

    :param float r: Radius
    :param array-like center: Local origin of the sphere
    :param string type: The type of parametrization ('radial' or 'square')
    :return: A solid ball
    :rtype: Volume
    """
    if type == 'radial':
        shell    = SurfaceFactory.sphere(r, center)
        midpoint = shell*0 + center
        return edge_surfaces(shell, midpoint)
    elif type == 'square':
        # based on the work of James E.Cobb: "Tiling the Sphere with Rational Bezier Patches"
        # University of Utah, July 11, 1988. UUCS-88-009
        b = BSplineBasis(order=5)
        sr2 = sqrt(2)
        sr3 = sqrt(3)
        sr6 = sqrt(6)
        cp = [[      -4*(sr3-1),       4*(1-sr3),      4*(1-sr3),   4*(3-sr3)  ], # row 0
              [           -sr2 ,     sr2*(sr3-4),    sr2*(sr3-4), sr2*(3*sr3-2)],
              [              0 ,  4./3*(1-2*sr3), 4./3*(1-2*sr3),4./3*(5-sr3)  ],
              [            sr2 ,     sr2*(sr3-4),    sr2*(sr3-4), sr2*(3*sr3-2)],
              [       4*(sr3-1),       4*(1-sr3),      4*(1-sr3),   4*(3-sr3)  ],
              [    -sr2*(4-sr3),            -sr2,    sr2*(sr3-4), sr2*(3*sr3-2)], # row 1
              [    -(3*sr3-2)/2,     (2-3*sr3)/2,     -(sr3+6)/2,     (sr3+6)/2],
              [              0 , sr2*(2*sr3-7)/3,       -5*sr6/3, sr2*(sr3+6)/3],
              [     (3*sr3-2)/2,     (2-3*sr3)/2,     -(sr3+6)/2,     (sr3+6)/2],
              [     sr2*(4-sr3),            -sr2,    sr2*(sr3-4), sr2*(3*sr3-2)],
              [ -4./3*(2*sr3-1),               0, 4./3*(1-2*sr3),   4*(5-sr3)/3], # row 2
              [-sr2/3*(7-2*sr3),               0,       -5*sr6/3, sr2*(sr3+6)/3],
              [              0 ,               0,    4*(sr3-5)/3, 4*(5*sr3-1)/9],
              [ sr2/3*(7-2*sr3),               0,       -5*sr6/3, sr2*(sr3+6)/3],
              [  4./3*(2*sr3-1),               0, 4./3*(1-2*sr3),   4*(5-sr3)/3],
              [    -sr2*(4-sr3),             sr2,    sr2*(sr3-4), sr2*(3*sr3-2)], # row 3
              [    -(3*sr3-2)/2,    -(2-3*sr3)/2,     -(sr3+6)/2,     (sr3+6)/2],
              [              0 ,-sr2*(2*sr3-7)/3,       -5*sr6/3, sr2*(sr3+6)/3],
              [     (3*sr3-2)/2,    -(2-3*sr3)/2,     -(sr3+6)/2,     (sr3+6)/2],
              [     sr2*(4-sr3),             sr2,    sr2*(sr3-4), sr2*(3*sr3-2)],
              [      -4*(sr3-1),      -4*(1-sr3),      4*(1-sr3),   4*(3-sr3)  ], # row 4
              [           -sr2 ,    -sr2*(sr3-4),    sr2*(sr3-4), sr2*(3*sr3-2)],
              [              0 , -4./3*(1-2*sr3), 4./3*(1-2*sr3),4./3*(5-sr3)  ],
              [            sr2 ,    -sr2*(sr3-4),    sr2*(sr3-4), sr2*(3*sr3-2)],
              [       4*(sr3-1),      -4*(1-sr3),      4*(1-sr3),   4*(3-sr3)  ]]
        wmin = Surface(b,b,cp, rational=True)
        wmax = wmin.clone().mirror([0,0,1])
        vmax = wmin.clone().rotate(pi/2, [1,0,0])
        vmin = vmax.clone().mirror([0,1,0])
        umax = vmin.clone().rotate(pi/2, [0,0,1])
        umin = umax.clone().mirror([1,0,0])
        # ideally I would like to call edge_surfaces() now, but that function
        # does not work with rational surfaces, so we'll just manually try
        # and add some inner controlpoints
        cp   = np.zeros((5,5,5,4))
        cp[ :, :, 0,:] = wmin[:,:,:]
        cp[ :, :,-1,:] = wmax[:,:,:]
        cp[ :, 0, :,:] = vmin[:,:,:]
        cp[ :,-1, :,:] = vmax[:,:,:]
        cp[ 0, :, :,:] = umin[:,:,:]
        cp[-1, :, :,:] = umax[:,:,:]
        inner = np.linspace(-.5,.5, 3)
        Y, X, Z = np.meshgrid(inner,inner,inner)
        cp[1:4,1:4,1:4,0] = X
        cp[1:4,1:4,1:4,1] = Y
        cp[1:4,1:4,1:4,2] = Z
        cp[1:4,1:4,1:4,3] = 1
        ball = Volume(b,b,b,cp,rational=True, raw=True)
        return r*ball + center
    else:
        raise ValueError('invalid type argument')