Пример #1
0
    def test_force_rational(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1, 2], [1, 0, 2], [1, 1, 2],
                         [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0], [4, 1, 0], [3, 2, 0],
                         [0, 0, 3], [-1, 1, 3], [0, 2, 3], [1, -1, 5], [1, 0, 5], [1, 1, 5],
                         [2, 1, 4], [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, .66, .32)
        control_point1 = vol[0]
        vol.force_rational()
        evaluation_point2 = vol(0.23, .66, .32)
        control_point2 = vol[0]
        # ensure that volume 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])
        # ensure that we include rational weights of 1
        self.assertEqual(len(control_point1), 3)
        self.assertEqual(len(control_point2), 4)
        self.assertEqual(control_point2[3], 1)
        self.assertEqual(vol.rational, True)
Пример #2
0
    def test_edge_surfaces_six_sides_issue_141(self):
        # create the unit cube
        vol = Volume()
        # modify slightly one edge: umin(w=0) is now a parabola instead of a line
        vol.raise_order(0,1,0)
        vol.controlpoints[-1, 1, 0, 0] += 1

        faces = vol.faces()

        # edge_surface should give back the same modified unit cube
        vol2 = vf.edge_surfaces(faces)

        # check discretization
        self.assertEqual(vol2.order(0),2)
        self.assertEqual(vol2.order(1),3)
        self.assertEqual(vol2.order(2),2)

        self.assertEqual(len(vol2.knots(0)),2) # [0, 1]
        self.assertEqual(len(vol2.knots(1)),2)
        self.assertEqual(len(vol2.knots(2)),2)

        # check a 5x5x5 evaluation grid
        u = np.linspace(0,1,5)
        v = np.linspace(0,1,5)
        w = np.linspace(0,1,5)
        pt  = vol( u,v,w)
        pt2 = vol2(u,v,w)

        self.assertTrue(np.allclose(pt, pt2))
Пример #3
0
    def test_evaluate(self):
        # creating the identity mapping by different size for all directions
        vol = Volume(BSplineBasis(7), BSplineBasis(6), BSplineBasis(5))

        # call evaluation at a 2x3x4 grid of points
        u_val = np.linspace(0, 1, 2)
        v_val = np.linspace(0, 1, 3)
        w_val = np.linspace(0, 1, 4)
        value = vol(u_val, v_val, w_val)
        self.assertEqual(value.shape[0], 2)  # 2 u-evaluation points
        self.assertEqual(value.shape[1], 3)  # 3 v-evaluation points
        self.assertEqual(value.shape[2], 4)  # 4 w-evaluation points
        self.assertEqual(value.shape[3], 3)  # 3 dimensions (x,y,z)
        self.assertEqual(vol.order(), (7, 6, 5))
        for i, u in enumerate(u_val):
            for j, v in enumerate(v_val):
                for k, w in enumerate(w_val):
                    self.assertAlmostEqual(value[i, j, k, 0], u)  # identity map x=u
                    self.assertAlmostEqual(value[i, j, k, 1], v)  # identity map y=v
                    self.assertAlmostEqual(value[i, j, k, 2], w)  # identity map z=w

        # test errors and exceptions
        with self.assertRaises(ValueError):
            val = vol(-10, .5, .5)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(+10, .3, .3)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, -10, .123)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, +10, .123)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, .2, +10)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, .2, -10)  # evalaute outside parametric domain
Пример #4
0
    def test_force_rational(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1,
                                                            2], [1, 0, 2],
                         [1, 1, 2], [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0],
                         [4, 1, 0], [3, 2, 0], [0, 0, 3], [-1, 1,
                                                           3], [0, 2, 3],
                         [1, -1, 5], [1, 0, 5], [1, 1, 5], [2, 1, 4],
                         [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, .66, .32)
        control_point1 = vol[0]
        vol.force_rational()
        evaluation_point2 = vol(0.23, .66, .32)
        control_point2 = vol[0]
        # ensure that volume 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])
        # ensure that we include rational weights of 1
        self.assertEqual(len(control_point1), 3)
        self.assertEqual(len(control_point2), 4)
        self.assertEqual(control_point2[3], 1)
        self.assertEqual(vol.rational, True)
Пример #5
0
    def test_evaluate(self):
        # creating the identity mapping by different size for all directions
        vol = Volume(BSplineBasis(7), BSplineBasis(6), BSplineBasis(5))

        # call evaluation at a 2x3x4 grid of points
        u_val = np.linspace(0, 1, 2)
        v_val = np.linspace(0, 1, 3)
        w_val = np.linspace(0, 1, 4)
        value = vol(u_val, v_val, w_val)
        self.assertEqual(value.shape[0], 2)  # 2 u-evaluation points
        self.assertEqual(value.shape[1], 3)  # 3 v-evaluation points
        self.assertEqual(value.shape[2], 4)  # 4 w-evaluation points
        self.assertEqual(value.shape[3], 3)  # 3 dimensions (x,y,z)
        self.assertEqual(vol.order(), (7, 6, 5))
        for i, u in enumerate(u_val):
            for j, v in enumerate(v_val):
                for k, w in enumerate(w_val):
                    self.assertAlmostEqual(value[i, j, k, 0], u)  # identity map x=u
                    self.assertAlmostEqual(value[i, j, k, 1], v)  # identity map y=v
                    self.assertAlmostEqual(value[i, j, k, 2], w)  # identity map z=w

        # test errors and exceptions
        with self.assertRaises(ValueError):
            val = vol(-10, .5, .5)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(+10, .3, .3)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, -10, .123)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, +10, .123)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, .2, +10)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, .2, -10)  # evalaute outside parametric domain
Пример #6
0
def cube(size=1, lower_left=(0, 0, 0)):
    """  Create a cube with parmetric origin at *(0,0,0)*.

    :param float size: Size(s), either a single scalar or a tuple of scalars per axis
    :param array-like lower_left: local origin, the lower bottom left corner of the cube
    :return: A linear parametrized box
    :rtype: Volume
    """
    result = Volume()
    result.scale(size)
    result += lower_left
    return result
Пример #7
0
    def test_controlpoint_access(self):
        v = Volume()
        v.refine(1)
        self.assertAlmostEqual(v[0,0,0, 0] ,  0)
        self.assertAlmostEqual(v[0,0,0][0] ,  0)
        self.assertAlmostEqual(v[0,1,0][0] ,  0)
        self.assertAlmostEqual(v[0,1,0][1] , .5)
        self.assertAlmostEqual(v[0,1,0, 1] , .5)
        self.assertAlmostEqual(v[0,0,2][2] ,  1)
        self.assertAlmostEqual(v[4][0]     , .5)
        self.assertAlmostEqual(v[4][1]     , .5)
        self.assertAlmostEqual(v[4][2]     ,  0)
        self.assertAlmostEqual(v[13][0]    , .5)
        self.assertAlmostEqual(v[13][1]    , .5)
        self.assertAlmostEqual(v[13][2]    , .5)
        self.assertAlmostEqual(v[14][0]    ,  1)
        self.assertAlmostEqual(v[14][1]    , .5)
        self.assertAlmostEqual(v[14][2]    , .5)

        v[0]        = [.1, .1, .1]
        v[1,1,1]    = [.6, .6, .6]
        v[1,0,0][0] = .4
        self.assertAlmostEqual(v[0,0,0][0], .1)
        self.assertAlmostEqual(v[0,0,0][1], .1)
        self.assertAlmostEqual(v[0,0,0][2], .1)
        self.assertAlmostEqual(v[13][0]   , .6)
        self.assertAlmostEqual(v[13][1]   , .6)
        self.assertAlmostEqual(v[13][2]   , .6)
        self.assertAlmostEqual(v[1][0]    , .4)
        self.assertAlmostEqual(v[1][1]    ,  0)
        self.assertAlmostEqual(v[1][2]    ,  0)

        v[:,0,0]         = 13
        v[0,1,0][:]      = 12
        # v[0,2,1]         = [9,8,7]
        # v[0,2,0]         = [9,8,7]
        v[0,2,1::-1]   = [9,8,7]
        v[1,2,1::-1,:] = [[6,5,4],[3,2,1]]
        self.assertAlmostEqual(v[1,0,0,0], 13)
        self.assertAlmostEqual(v[1,0,0,1], 13)
        self.assertAlmostEqual(v[2,0,0,2], 13)
        self.assertAlmostEqual(v[0,1,0,0], 12)
        self.assertAlmostEqual(v[0,1,0,2], 12)
        self.assertAlmostEqual(v[0,2,2,1],  1)
        self.assertAlmostEqual(v[0,2,1,0],  9)
        self.assertAlmostEqual(v[0,2,1,1],  8)
        self.assertAlmostEqual(v[0,2,0,2],  7)
        self.assertAlmostEqual(v[1,2,1,0],  6)
        self.assertAlmostEqual(v[1,2,1,1],  5)
        self.assertAlmostEqual(v[1,2,1,2],  4)
        self.assertAlmostEqual(v[1,2,0,0],  3)
        self.assertAlmostEqual(v[1,2,0,1],  2)
        self.assertAlmostEqual(v[1,2,0,2],  1)
Пример #8
0
    def test_controlpoint_access(self):
        v = Volume()
        v.refine(1)
        self.assertAlmostEqual(v[0, 0, 0, 0], 0)
        self.assertAlmostEqual(v[0, 0, 0][0], 0)
        self.assertAlmostEqual(v[0, 1, 0][0], 0)
        self.assertAlmostEqual(v[0, 1, 0][1], .5)
        self.assertAlmostEqual(v[0, 1, 0, 1], .5)
        self.assertAlmostEqual(v[0, 0, 2][2], 1)
        self.assertAlmostEqual(v[4][0], .5)
        self.assertAlmostEqual(v[4][1], .5)
        self.assertAlmostEqual(v[4][2], 0)
        self.assertAlmostEqual(v[13][0], .5)
        self.assertAlmostEqual(v[13][1], .5)
        self.assertAlmostEqual(v[13][2], .5)
        self.assertAlmostEqual(v[14][0], 1)
        self.assertAlmostEqual(v[14][1], .5)
        self.assertAlmostEqual(v[14][2], .5)

        v[0] = [.1, .1, .1]
        v[1, 1, 1] = [.6, .6, .6]
        v[1, 0, 0][0] = .4
        self.assertAlmostEqual(v[0, 0, 0][0], .1)
        self.assertAlmostEqual(v[0, 0, 0][1], .1)
        self.assertAlmostEqual(v[0, 0, 0][2], .1)
        self.assertAlmostEqual(v[13][0], .6)
        self.assertAlmostEqual(v[13][1], .6)
        self.assertAlmostEqual(v[13][2], .6)
        self.assertAlmostEqual(v[1][0], .4)
        self.assertAlmostEqual(v[1][1], 0)
        self.assertAlmostEqual(v[1][2], 0)

        v[:, 0, 0] = 13
        v[0, 1, 0][:] = 12
        # v[0,2,1]         = [9,8,7]
        # v[0,2,0]         = [9,8,7]
        v[0, 2, 1::-1] = [9, 8, 7]
        v[1, 2, 1::-1, :] = [[6, 5, 4], [3, 2, 1]]
        self.assertAlmostEqual(v[1, 0, 0, 0], 13)
        self.assertAlmostEqual(v[1, 0, 0, 1], 13)
        self.assertAlmostEqual(v[2, 0, 0, 2], 13)
        self.assertAlmostEqual(v[0, 1, 0, 0], 12)
        self.assertAlmostEqual(v[0, 1, 0, 2], 12)
        self.assertAlmostEqual(v[0, 2, 2, 1], 1)
        self.assertAlmostEqual(v[0, 2, 1, 0], 9)
        self.assertAlmostEqual(v[0, 2, 1, 1], 8)
        self.assertAlmostEqual(v[0, 2, 0, 2], 7)
        self.assertAlmostEqual(v[1, 2, 1, 0], 6)
        self.assertAlmostEqual(v[1, 2, 1, 1], 5)
        self.assertAlmostEqual(v[1, 2, 1, 2], 4)
        self.assertAlmostEqual(v[1, 2, 0, 0], 3)
        self.assertAlmostEqual(v[1, 2, 0, 1], 2)
        self.assertAlmostEqual(v[1, 2, 0, 2], 1)
Пример #9
0
def cube(size=1, lower_left=(0,0,0)):
    """  Create a cube with parmetric origin at *(0,0,0)*.

    :param float size: Size(s), either a single scalar or a tuple of scalars per axis
    :param array-like lower_left: local origin, the lower bottom left corner of the cube
    :return: A linear parametrized box
    :rtype: Volume
    """
    result = Volume()
    result.scale(size)
    result += lower_left
    return result
Пример #10
0
    def test_permute_and_flip(self):
        v1 = Volume()
        v2 = Volume()

        v2.swap('u', 'v')
        v2.reverse('v')
        v2.swap('u', 'w')
        ori = Orientation.compute(v1, v2)
        self.assertEqual(ori.perm, (1, 2, 0))
        self.assertEqual(ori.flip, (True, False, False))
Пример #11
0
    def test_map_section(self):
        v1 = Volume()
        v2 = Volume()

        v2.swap('u', 'v')
        v2.reverse('v')
        v2.swap('u', 'w')
        ori = Orientation.compute(v1, v2)
        self.assertEqual(ori.map_section((-1, 0, -1)), (-1, -1, -1))
        self.assertEqual(ori.map_section((0, 0, None)), (-1, None, 0))
Пример #12
0
    def test_lookup(self):
        model = SplineModel(3, 3)
        v = Volume().refine(1, 1, 1)
        model.add(v)
        model.add(v + (1, 0, 0))
        model.add(v + (0, 0, 1))

        q = Volume().refine(1, 1, 1)
        self.assertIs(model[q].node, model[v].node)

        q = Volume().refine(1, 1, 1).reverse('u').swap('u', 'v')
        self.assertIs(model[q].node, model[v].node)

        self.assertIs(model[v.section(w=-1)].node,
                      model[(v + (0, 0, 1)).section(w=0)].node)
Пример #13
0
    def test_map_array(self):
        v1 = Volume()
        v2 = Volume()

        v2.swap('u', 'v')
        v2.reverse('v')
        v2.swap('u', 'w')
        ori = Orientation.compute(v1, v2)
        self.assertTrue((ori.map_array(
            np.reshape(np.arange(8, dtype=int),
                       (2, 2, 2))) == np.reshape([2, 6, 3, 7, 0, 4, 1, 5],
                                                 (2, 2, 2))).all())
Пример #14
0
    def test_raise_order(self):
        # more or less random 3D volume with p=[2,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 0], [-1, 1, 0], [0, 2, 0], [1, -1, 0], [1, 0, 0], [1, 1, 0],
                         [2, 1, 0], [2, 2, 0], [2, 3, 0], [3, 0, 0], [4, 1, 0], [3, 2, 0],
                         [0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1, 2], [1, 0, 2], [1, 1, 2],
                         [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 1], [4, 1, 1], [3, 2, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        self.assertEqual(vol.order(), (3, 3, 2))
        evaluation_point1 = vol(0.23, 0.37, 0.44)  # pick some evaluation point (could be anything)

        vol.raise_order(1, 2, 4)

        self.assertEqual(vol.order(), (4, 5, 6))
        evaluation_point2 = vol(0.23, 0.37, 0.44)

        # evaluation before and after RaiseOrder should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])

        # test a rational 3D volume
        controlpoints = [[0, 0, 1, 1], [-1, 1, .96, 1], [0, 2, 1, 1], [1, -1, 1, 1], [1, 0, .8, 1],
                         [1, 1, 1, 1], [2, 1, .89, 1], [2, 2, .9, 1], [2, 3, 1, 1], [3, 0, 1, 1],
                         [4, 1, 1, 1], [3, 2, 1, 1], [0, 0, 1, 2], [-1, 1, .7, 2], [0, 2, 1.3, 2],
                         [1, -1, 1, 2], [1, 0, .77, 2], [1, 1, 1, 2], [2, 1, .89, 1], [2, 2, .8, 4],
                         [2, 3, 1, 1], [3, 0, 1, 1], [4, 1, 1, 1], [3, 2, 1, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints, True)

        self.assertEqual(vol.order()[0], 3)
        self.assertEqual(vol.order()[1], 3)
        evaluation_point1 = vol(0.23, 0.37, 0.44)

        vol.raise_order(1, 2, 1)

        self.assertEqual(vol.order(), (4, 5, 3))
        evaluation_point2 = vol(0.23, 0.37, 0.44)

        # evaluation before and after RaiseOrder should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])
Пример #15
0
def interpolate(x, bases, u=None):
    """  Interpolate a volume on a set of regular gridded interpolation points `x`.

    The points can be either a matrix (in which case the first index is
    interpreted as a flat row-first index of the interpolation grid) or a 4D
    tensor. In both cases the last index is the physical coordinates.

    :param numpy.ndarray x: Grid of interpolation points
    :param [BSplineBasis] bases: The basis to interpolate on
    :param [array-like] u: Parametric interpolation points, defaults to
        Greville points of the basis
    :return: Interpolated volume
    :rtype: Volume
    """
    vol_shape = [b.num_functions() for b in bases]
    dim = x.shape[-1]
    if len(x.shape) == 2:
        x = x.reshape(vol_shape + [dim])
    if u is None:
        u = [b.greville() for b in bases]
    N_all = [b(t) for b, t in zip(bases, u)]
    N_all.reverse()
    cp = x
    for N in N_all:
        cp = np.tensordot(np.linalg.inv(N), cp, axes=(1, 2))

    return Volume(bases[0], bases[1], bases[2],
                  cp.transpose(2, 1, 0, 3).reshape((np.prod(vol_shape), dim)))
Пример #16
0
def least_square_fit(x, bases, u):
    """  Perform a least-square fit of a point cloud `x` onto a spline basis.

    The points can be either a matrix (in which case the first index is
    interpreted as a flat row-first index of the interpolation grid) or a 4D
    tensor. In both cases the last index is the physical coordinates.

    There must be at least as many points as basis functions.

    :param numpy.ndarray x: Grid of evaluation points
    :param [BSplineBasis] bases: Basis on which to interpolate
    :param [array-like] u: Parametric values at evaluation points
    :return: Approximated volume
    :rtype: Volume
    """
    vol_shape = [b.num_functions() for b in bases]
    dim = x.shape[-1]
    if len(x.shape) == 2:
        x = x.reshape(vol_shape + [dim])
    N_all = [b(t) for b, t in zip(bases, u)]
    N_all.reverse()
    cp = x
    for N in N_all:
        cp = np.tensordot(N.T, cp, axes=(1, 2))
    for N in N_all:
        cp = np.tensordot(np.linalg.inv(N.T * N), cp, axes=(1, 2))

    return Volume(bases[0], bases[1], bases[2],
                  cp.transpose(2, 1, 0, 3).reshape((np.prod(vol_shape), dim)))
Пример #17
0
    def read(self):
        lines = self.lines()

        version = next(lines).split()
        assert version[0] == 'C'
        assert version[3] == '0'  # No support for rational SPL yet
        pardim = int(version[1])
        physdim = int(version[2])

        orders = [int(k) for k in islice(lines, pardim)]
        ncoeffs = [int(k) for k in islice(lines, pardim)]
        totcoeffs = int(np.prod(ncoeffs))
        nknots = [a + b for a, b in zip(orders, ncoeffs)]

        next(lines)  # Skip spline accuracy

        knots = [[float(k) for k in islice(lines, nkts)] for nkts in nknots]
        bases = [BSplineBasis(p, kts, -1) for p, kts in zip(orders, knots)]

        cpts = np.array([float(k) for k in islice(lines, totcoeffs * physdim)])
        cpts = cpts.reshape(physdim, *(ncoeffs[::-1])).transpose()

        if pardim == 1:
            patch = Curve(*bases, controlpoints=cpts, raw=True)
        elif pardim == 2:
            patch = Surface(*bases, controlpoints=cpts, raw=True)
        elif pardim == 3:
            patch = Volume(*bases, controlpoints=cpts, raw=True)
        else:
            patch = SplineObject(bases, controlpoints=cpts, raw=True)

        return [patch]
Пример #18
0
    def test_indexing(self):
        v = Volume()

        self.assertEqual(v[0][0], 0.0)
        self.assertEqual(v[0][1], 0.0)
        self.assertEqual(v[0][2], 0.0)
        self.assertEqual(v[1][0], 1.0)
        self.assertEqual(v[1][1], 0.0)
        self.assertEqual(v[1][2], 0.0)
        self.assertEqual(v[-1][0], 1.0)
        self.assertEqual(v[-1][1], 1.0)
        self.assertEqual(v[-1][2], 1.0)

        self.assertEqual(v[:][0, 0], 0.0)
        self.assertEqual(v[:][1, 0], 1.0)
        self.assertEqual(v[:][1, 1], 0.0)
        self.assertEqual(v[:][2, 1], 1.0)
        self.assertEqual(v[:][2, 2], 0.0)
        self.assertEqual(v[:][5, 0], 1.0)
        self.assertEqual(v[:][5, 1], 0.0)
        self.assertEqual(v[:][5, 2], 1.0)

        self.assertEqual(v[0, 0, 0][0], 0.0)
        self.assertEqual(v[0, 0, 0][1], 0.0)
        self.assertEqual(v[0, 0, 0][2], 0.0)
        self.assertEqual(v[0, 1, 0][0], 0.0)
        self.assertEqual(v[0, 1, 0][1], 1.0)
        self.assertEqual(v[0, 1, 0][2], 0.0)
        self.assertEqual(v[0, :, 1][0, 0], 0.0)
        self.assertEqual(v[0, :, 1][0, 1], 0.0)
        self.assertEqual(v[0, :, 1][0, 2], 1.0)
        self.assertEqual(v[0, :, 1][1, 0], 0.0)
        self.assertEqual(v[0, :, 1][1, 1], 1.0)
        self.assertEqual(v[0, :, 1][1, 2], 1.0)
Пример #19
0
    def test_edge_surfaces_six_sides(self):
        # create the unit cube
        vol = Volume()
        vol.raise_order(2,2,2)
        vol.refine(3)

        edges = vol.faces()

        # edge_surface should give back the same unit cube
        vol2 = vf.edge_surfaces(edges)

        # check discretization
        self.assertEqual(vol2.order(0), 4)
        self.assertEqual(vol2.order(1), 4)
        self.assertEqual(vol2.order(2), 4)

        self.assertEqual(len(vol2.knots(0)), 5) # [0,.25,.5,.75,1]
        self.assertEqual(len(vol2.knots(1)), 5)
        self.assertEqual(len(vol2.knots(2)), 5)

        # check a 5x5x5 evaluation grid
        u = np.linspace(0,1,5)
        v = np.linspace(0,1,5)
        w = np.linspace(0,1,5)
        pt  = vol( u,v,w)
        pt2 = vol2(u,v,w)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)
Пример #20
0
 def get_mixed_cont_mesh(self):
     # Create mixed discontinuity mesh: C^0, C^0, C^{-1}
     nx, ny, nz = self.n
     Xz = self.raw.get_discontinuous_z()
     b1 = BSplineBasis(2, sorted(list(range(self.n[0]+1))+[0,self.n[0]]))
     b2 = BSplineBasis(2, sorted(list(range(self.n[1]+1))+[0,self.n[1]]))
     b3 = BSplineBasis(2, sorted(list(range(self.n[2]+1))*2))
     true_vol = Volume(b1, b2, b3, Xz, raw=True)
     return true_vol
Пример #21
0
def get_spline(spline, n, p, rational=False):
    basis = BSplineBasis(p, [0]*(p-1) + list(range(n-p+2)) + [n-p+1]*(p-1))
    if spline == 'curve':
        return Curve(basis, rational=rational)
    elif spline == 'surface':
        return Surface(basis, basis, rational=rational)
    elif spline == 'volume':
        return Volume(basis, basis, basis, rational=rational)
    return None
Пример #22
0
    def test_make_identical(self):
        basis1 = BSplineBasis(4, [-1,-1,0,0,1,1,2,2], periodic=1)
        basis2 = BSplineBasis(3, [-1,0,0,1,1,2],      periodic=0)
        basis3 = BSplineBasis(2)
        vol1 = Volume()
        vol2 = Volume(basis1, basis2, basis3)
        vol1.refine(1)
        Volume.make_splines_identical(vol1,vol2)

        for v in (vol1, vol2):
            self.assertEqual(v.periodic(0), False)
            self.assertEqual(v.periodic(1), False)
            self.assertEqual(v.periodic(2), False)

            self.assertEqual(v.order(), (4,3,2))
            self.assertAlmostEqual(len(v.knots(0, True)), 11)
            self.assertAlmostEqual(len(v.knots(1, True)), 8)
            self.assertAlmostEqual(len(v.knots(2, True)), 5)
Пример #23
0
 def get_cm1_mesh(self):
     # Create the C^{-1} mesh
     nx, ny, nz = self.n
     Xm1 = self.raw.get_discontinuous_all()
     b1 = BSplineBasis(2, sorted(list(range(self.n[0]+1))*2))
     b2 = BSplineBasis(2, sorted(list(range(self.n[1]+1))*2))
     b3 = BSplineBasis(2, sorted(list(range(self.n[2]+1))*2))
     discont_vol = Volume(b1, b2, b3, Xm1)
     return discont_vol
Пример #24
0
    def test_operators(self):
        v = Volume()
        v.raise_order(1,1,2)
        v.refine(3,2,1)

        # test translation operator
        v2 = v + [1,0,0]
        v3 = [1,0,0] + v
        v += [1,0,0]
        self.assertTrue(np.allclose(v2.controlpoints, v3.controlpoints))
        self.assertTrue(np.allclose(v.controlpoints,  v3.controlpoints))

        # test scaling operator
        v2 = v * 3
        v3 = 3 * v
        v *= 3
        self.assertTrue(np.allclose(v2.controlpoints, v3.controlpoints))
        self.assertTrue(np.allclose(v.controlpoints,  v3.controlpoints))
Пример #25
0
    def test_swap(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1,
                                                            2], [1, 0, 2],
                         [1, 1, 2], [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0],
                         [4, 1, 0], [3, 2, 0], [0, 0, 3], [-1, 1,
                                                           3], [0, 2, 3],
                         [1, -1, 5], [1, 0, 5], [1, 1, 5], [2, 1, 4],
                         [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, .56, .12)
        control_point1 = vol[
            1]  # this is control point i=(1,0,0), when n=(4,3,2)
        self.assertEqual(vol.order(), (4, 3, 2))
        vol.swap(0, 1)
        evaluation_point2 = vol(0.56, .23, .12)
        control_point2 = vol[
            3]  # this is control point i=(0,1,0), when n=(3,4,2)
        self.assertEqual(vol.order(), (3, 4, 2))

        # ensure that volume 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])

        # check that the control points have re-ordered themselves
        self.assertEqual(control_point1[0], control_point2[0])
        self.assertEqual(control_point1[1], control_point2[1])
        self.assertEqual(control_point1[2], control_point2[2])

        vol.swap(1, 2)
        evaluation_point3 = vol(.56, .12, .23)
        control_point3 = vol[
            6]  # this is control point i=(0,0,1), when n=(3,2,4)
        self.assertEqual(vol.order(), (3, 2, 4))

        # ensure that volume 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])

        # check that the control points have re-ordered themselves
        self.assertEqual(control_point1[0], control_point3[0])
        self.assertEqual(control_point1[1], control_point3[1])
        self.assertEqual(control_point1[2], control_point3[2])
Пример #26
0
    def test_edge_surfaces_six_sides(self):
        # create the unit cube
        vol = Volume()
        vol.raise_order(2,2,2)
        vol.refine(3)

        edges = vol.faces()

        # edge_surface should give back the same unit cube
        vol2 = VolumeFactory.edge_surfaces(edges)

        # check discretization
        self.assertEqual(vol2.order(0), 4)
        self.assertEqual(vol2.order(1), 4)
        self.assertEqual(vol2.order(2), 4)

        self.assertEqual(len(vol2.knots(0)), 5) # [0,.25,.5,.75,1]
        self.assertEqual(len(vol2.knots(1)), 5)
        self.assertEqual(len(vol2.knots(2)), 5)

        # check a 5x5x5 evaluation grid
        u = np.linspace(0,1,5)
        v = np.linspace(0,1,5)
        w = np.linspace(0,1,5)
        pt  = vol( u,v,w)
        pt2 = vol2(u,v,w)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)
Пример #27
0
    def test_faces(self):
        vol1 = Volume()
        faces = vol1.faces()
        self.assertEqual(len(faces), 6)
        # check that it all comes out in the order umin, umax, vmin, vmax, wmin, wmax
        self.assertTrue(np.allclose(faces[0][0, 0], (0, 0, 0)))
        self.assertTrue(np.allclose(faces[0][1, 1], (0, 1, 1)))
        self.assertTrue(np.allclose(faces[1][0, 0], (1, 0, 0)))
        self.assertTrue(np.allclose(faces[1][1, 1], (1, 1, 1)))
        self.assertTrue(np.allclose(faces[2][0, 0], (0, 0, 0)))
        self.assertTrue(np.allclose(faces[2][1, 1], (1, 0, 1)))
        self.assertTrue(np.allclose(faces[3][0, 0], (0, 1, 0)))
        self.assertTrue(np.allclose(faces[3][1, 1], (1, 1, 1)))
        self.assertTrue(np.allclose(faces[4][0, 0], (0, 0, 0)))
        self.assertTrue(np.allclose(faces[4][1, 1], (1, 1, 0)))
        self.assertTrue(np.allclose(faces[5][0, 0], (0, 0, 1)))
        self.assertTrue(np.allclose(faces[5][1, 1], (1, 1, 1)))

        # one parametric direction is periodic, these indices should return None
        vol2 = vf.cylinder()
        faces = vol2.faces()
        self.assertEqual(len(faces), 6)
        self.assertIsNotNone(faces[0])
        self.assertIsNotNone(faces[1])
        self.assertIsNone(faces[2])
        self.assertIsNone(faces[3])
        self.assertIsNotNone(faces[4])
        self.assertIsNotNone(faces[5])

        # two parametric directions are periodic
        vol3 = vf.torus()
        faces = vol3.faces()
        self.assertEqual(len(faces), 6)
        self.assertIsNotNone(faces[0])
        self.assertIsNotNone(faces[1])
        self.assertIsNone(faces[2])
        self.assertIsNone(faces[3])
        self.assertIsNone(faces[4])
        self.assertIsNone(faces[5])
Пример #28
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
Пример #29
0
    def test_permute(self):
        v1 = Volume()
        v2 = Volume()

        v2.swap('u', 'v')
        ori = Orientation.compute(v1, v2)
        self.assertEqual(ori.perm, (1, 0, 2))
        self.assertEqual(ori.flip, (False, False, False))

        v2.swap('v', 'w')
        ori = Orientation.compute(v1, v2)
        self.assertEqual(ori.perm, (2, 0, 1))
        self.assertEqual(ori.flip, (False, False, False))
Пример #30
0
    def test_flip(self):
        v1 = Volume()
        v2 = Volume()

        v2.reverse('u')
        ori = Orientation.compute(v1, v2)
        self.assertEqual(ori.perm, (0, 1, 2))
        self.assertEqual(ori.flip, (True, False, False))

        v2.reverse('w')
        ori = Orientation.compute(v1, v2)
        self.assertEqual(ori.perm, (0, 1, 2))
        self.assertEqual(ori.flip, (True, False, True))
Пример #31
0
    def test_evaluate_nontensor(self):
        vol = Volume(BSplineBasis(7), BSplineBasis(7), BSplineBasis(5))

        u_val = [0, 0.1, 0.9, 0.3]
        v_val = [0.2, 0.3, 0.9, 0.4]
        w_val = [0.3, 0.5, 0.5, 0.0]
        value = vol(u_val, v_val, w_val, tensor=False)

        self.assertEqual(value.shape[0], 4)
        self.assertEqual(value.shape[1], 3)

        for i, (u, v, w) in enumerate(zip(u_val, v_val, w_val)):
            self.assertAlmostEqual(value[i, 0], u)  # identity map x=u
            self.assertAlmostEqual(value[i, 1], v)  # identity map y=v
            self.assertAlmostEqual(value[i, 2], w)  # identity map z=w
Пример #32
0
    def test_reverse(self):
        # identity mapping, control points generated from knot vector
        basis1 = BSplineBasis(4, [2, 2, 2, 2, 3, 6, 12, 12, 12, 12])
        basis2 = BSplineBasis(3, [-3, -3, -3, 20, 30, 33, 33, 33])
        basis3 = BSplineBasis(5, [0, 0, 0, 0, 0, 8, 8, 8, 8, 8])
        vol = Volume(basis1, basis2, basis3)

        u = np.linspace(2, 12, 5)
        v = np.linspace(-3, 33, 5)
        w = np.linspace(0, 8, 5)

        pt = vol(u, v, w)

        vol.reverse('v')
        pt2 = vol(u, v[::-1], w)
        self.assertAlmostEqual(np.linalg.norm(pt - pt2), 0.0)
        self.assertAlmostEqual(vol.start('v'), -3)
        self.assertAlmostEqual(vol.end('v'), 33)

        vol.reverse(2)
        pt2 = vol(u, v[::-1], w[::-1])
        self.assertAlmostEqual(np.linalg.norm(pt - pt2), 0.0)
        self.assertAlmostEqual(vol.start('w'), 0)
        self.assertAlmostEqual(vol.end('w'), 8)
Пример #33
0
    def test_cp_numbering(self):
        model = SplineModel(3, 3)
        v = Volume().refine(1, 1, 1)
        model.add(v)
        model.add(v + (1, 0, 0))
        model.add(v + (0, 0, 1))

        # Predictable numbering of control points
        model.generate_cp_numbers()
        cps = model.cps()
        self.assertEqual(cps.shape, (63, 3))
        np.testing.assert_almost_equal(cps[:27],
                                       v.controlpoints.reshape(-1, 3))
        np.testing.assert_almost_equal(
            cps[27:45], v.controlpoints[1:].reshape(-1, 3) + (1, 0, 0))
        np.testing.assert_almost_equal(
            cps[45:], v.controlpoints[:, :, 1:].reshape(-1, 3) + (0, 0, 1))
Пример #34
0
    def test_cell_numbering(self):
        model = SplineModel(3, 3)
        v = Volume().refine(1, 1, 1)
        model.add(v)
        model.add(v + (1, 0, 0))
        model.add(v + (0, 0, 1))

        # Predictable numbering of cells
        model.generate_cell_numbers()
        self.assertTrue((model[v].node.cell_numbers.flatten() == np.arange(
            8, dtype=int)).all())
        self.assertTrue(
            (model[v + (1, 0, 0)].node.cell_numbers.flatten() == np.arange(
                8, 16, dtype=int)).all())
        self.assertTrue(
            (model[v + (0, 0, 1)].node.cell_numbers.flatten() == np.arange(
                16, 24, dtype=int)).all())
Пример #35
0
    def test_swap(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1, 2], [1, 0, 2], [1, 1, 2],
                         [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0], [4, 1, 0], [3, 2, 0],
                         [0, 0, 3], [-1, 1, 3], [0, 2, 3], [1, -1, 5], [1, 0, 5], [1, 1, 5],
                         [2, 1, 4], [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, .56, .12)
        control_point1 = vol[1]  # this is control point i=(1,0,0), when n=(4,3,2)
        self.assertEqual(vol.order(), (4, 3, 2))
        vol.swap(0, 1)
        evaluation_point2 = vol(0.56, .23, .12)
        control_point2 = vol[3]  # this is control point i=(0,1,0), when n=(3,4,2)
        self.assertEqual(vol.order(), (3, 4, 2))

        # ensure that volume 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])

        # check that the control points have re-ordered themselves
        self.assertEqual(control_point1[0], control_point2[0])
        self.assertEqual(control_point1[1], control_point2[1])
        self.assertEqual(control_point1[2], control_point2[2])

        vol.swap(1, 2)
        evaluation_point3 = vol(.56, .12, .23)
        control_point3 = vol[6]  # this is control point i=(0,0,1), when n=(3,2,4)
        self.assertEqual(vol.order(), (3, 2, 4))

        # ensure that volume 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])

        # check that the control points have re-ordered themselves
        self.assertEqual(control_point1[0], control_point3[0])
        self.assertEqual(control_point1[1], control_point3[1])
        self.assertEqual(control_point1[2], control_point3[2])
Пример #36
0
def extrude(surf, amount):
    """  Extrude a surface by sweeping it to a given height.

    :param Surface surf: Surface to extrude
    :param array-like amount: 3-component vector of sweeping amount and direction
    :return: The extruded surface
    :rtype: Volume
    """
    surf.set_dimension(3)  # add z-components (if not already present)
    cp = []
    for controlpoint in surf:
        cp.append(list(controlpoint))
    surf += amount
    for controlpoint in surf:
        cp.append(list(controlpoint))
    surf -= amount
    return Volume(surf.bases[0], surf.bases[1], BSplineBasis(2), cp,
                  surf.rational)
Пример #37
0
    def test_bounding_box(self):
        vol = Volume()
        bb = vol.bounding_box()
        self.assertAlmostEqual(bb[0][0], 0)
        self.assertAlmostEqual(bb[0][1], 1)
        self.assertAlmostEqual(bb[1][0], 0)
        self.assertAlmostEqual(bb[1][1], 1)
        self.assertAlmostEqual(bb[2][0], 0)
        self.assertAlmostEqual(bb[2][1], 1)

        vol.refine(2)
        vol.rotate(pi / 4, [1, 0, 0])
        vol += (1, 0, 1)
        bb = vol.bounding_box()
        self.assertAlmostEqual(bb[0][0], 1)
        self.assertAlmostEqual(bb[0][1], 2)
        self.assertAlmostEqual(bb[1][0], -sqrt(2) / 2)
        self.assertAlmostEqual(bb[1][1], sqrt(2) / 2)
        self.assertAlmostEqual(bb[2][0], 1)
        self.assertAlmostEqual(bb[2][1], 1 + sqrt(2))
Пример #38
0
    def test_reverse(self):
        # identity mapping, control points generated from knot vector
        basis1 = BSplineBasis(4, [2,2,2,2,3,6,12,12,12,12])
        basis2 = BSplineBasis(3, [-3,-3,-3,20,30,33,33,33])
        basis3 = BSplineBasis(5, [0,0,0,0,0,8,8,8,8,8])
        vol = Volume(basis1, basis2, basis3)
        
        u = np.linspace( 2,12,5)
        v = np.linspace(-3,33,5)
        w = np.linspace( 0, 8,5)

        pt = vol(u,v,w)

        vol.reverse('v')
        pt2 = vol(u,v[::-1],w)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)
        self.assertAlmostEqual(vol.start('v'),  -3)
        self.assertAlmostEqual(vol.end('v'),    33)

        vol.reverse(2)
        pt2 = vol(u,v[::-1],w[::-1])
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)
        self.assertAlmostEqual(vol.start('w'),   0)
        self.assertAlmostEqual(vol.end('w'),     8)
Пример #39
0
    def test_make_identical(self):
        basis1 = BSplineBasis(4, [-1, -1, 0, 0, 1, 1, 2, 2], periodic=1)
        basis2 = BSplineBasis(3, [-1, 0, 0, 1, 1, 2], periodic=0)
        basis3 = BSplineBasis(2)
        vol1 = Volume()
        vol2 = Volume(basis1, basis2, basis3)
        vol1.refine(1)
        Volume.make_splines_identical(vol1, vol2)

        for v in (vol1, vol2):
            self.assertEqual(v.periodic(0), False)
            self.assertEqual(v.periodic(1), False)
            self.assertEqual(v.periodic(2), False)

            self.assertEqual(v.order(), (4, 3, 2))
            self.assertAlmostEqual(len(v.knots(0, True)), 11)
            self.assertAlmostEqual(len(v.knots(1, True)), 8)
            self.assertAlmostEqual(len(v.knots(2, True)), 5)
Пример #40
0
    def test_node_counts(self):
        model = SplineModel(3, 3)
        v = Volume().refine(1, 1, 1)
        model.add(v)
        model.add(v + (1, 0, 0))
        model.add(v + (0, 0, 1))

        # 3 volumes
        cat = model.catalogue
        self.assertEqual(len(cat.top_nodes()), 3)

        # 16 faces
        cat = cat.lower
        self.assertEqual(len(cat.top_nodes()), 16)

        # 28 edges
        cat = cat.lower
        self.assertEqual(len(cat.top_nodes()), 28)

        # 16 vertices
        cat = cat.lower
        self.assertEqual(len(cat.top_nodes()), 16)
Пример #41
0
    def test_bounding_box(self):
        vol = Volume()
        bb = vol.bounding_box()
        self.assertAlmostEqual(bb[0][0], 0 )
        self.assertAlmostEqual(bb[0][1], 1 )
        self.assertAlmostEqual(bb[1][0], 0 )
        self.assertAlmostEqual(bb[1][1], 1 )
        self.assertAlmostEqual(bb[2][0], 0 )
        self.assertAlmostEqual(bb[2][1], 1 )

        vol.refine(2)
        vol.rotate(pi/4, [1,0,0])
        vol += (1,0,1)
        bb = vol.bounding_box()
        self.assertAlmostEqual(bb[0][0], 1 )
        self.assertAlmostEqual(bb[0][1], 2 )
        self.assertAlmostEqual(bb[1][0], -sqrt(2)/2 )
        self.assertAlmostEqual(bb[1][1],  sqrt(2)/2 )
        self.assertAlmostEqual(bb[2][0], 1 )
        self.assertAlmostEqual(bb[2][1], 1+sqrt(2) )
Пример #42
0
    def test_operators(self):
        v = Volume()
        v.raise_order(1, 1, 2)
        v.refine(3, 2, 1)

        # test translation operator
        v2 = v + [1, 0, 0]
        v3 = [1, 0, 0] + v
        v += [1, 0, 0]
        self.assertTrue(np.allclose(v2.controlpoints, v3.controlpoints))
        self.assertTrue(np.allclose(v.controlpoints, v3.controlpoints))

        # test scaling operator
        v2 = v * 3
        v3 = 3 * v
        v *= 3
        self.assertTrue(np.allclose(v2.controlpoints, v3.controlpoints))
        self.assertTrue(np.allclose(v.controlpoints, v3.controlpoints))
Пример #43
0
def edge_surfaces(*surfaces):
    """  Create the volume defined by the region between the input surfaces.

    In case of six input surfaces, these must be given in the order: bottom,
    top, left, right, back, front. Opposing sides must be parametrized in the
    same directions.

    :param [Surface] surfaces: Two or six edge surfaces
    :return: The enclosed volume
    :rtype: Volume
    :raises ValueError: If the length of *surfaces* is not two or six
    """
    if len(surfaces) == 1: # probably gives input as a list-like single variable
        surfaces = surfaces[0]
    if len(surfaces) == 2:
        surf1 = surfaces[0].clone()
        surf2 = surfaces[1].clone()
        Surface.make_splines_identical(surf1, surf2)
        (n1, n2, d) = surf1.controlpoints.shape  # d = dimension + rational

        controlpoints = np.zeros((n1, n2, 2, d))
        controlpoints[:, :, 0, :] = surf1.controlpoints
        controlpoints[:, :, 1, :] = surf2.controlpoints

        # Volume constructor orders control points in a different way, so we
        # create it from scratch here
        result = Volume(surf1.bases[0], surf1.bases[1], BSplineBasis(2), controlpoints,
                         rational=surf1.rational, raw=True)

        return result
    elif len(surfaces) == 6:
        if any([surf.rational for surf in surfaces]):
            raise RuntimeError('edge_surfaces not supported for rational splines')

        # coons patch (https://en.wikipedia.org/wiki/Coons_patch)
        umin = surfaces[0]
        umax = surfaces[1]
        vmin = surfaces[2]
        vmax = surfaces[3]
        wmin = surfaces[4]
        wmax = surfaces[5]
        vol1 = edge_surfaces(umin,umax)
        vol2 = edge_surfaces(vmin,vmax)
        vol3 = edge_surfaces(wmin,wmax)
        vol4 = Volume(controlpoints=vol1.corners(order='F'), rational=vol1.rational)
        vol1.swap(0, 2)
        vol1.swap(1, 2)
        vol2.swap(1, 2)
        vol4.swap(1, 2)
        Volume.make_splines_identical(vol1, vol2)
        Volume.make_splines_identical(vol1, vol3)
        Volume.make_splines_identical(vol1, vol4)
        Volume.make_splines_identical(vol2, vol3)
        Volume.make_splines_identical(vol2, vol4)
        Volume.make_splines_identical(vol3, vol4)
        result                =   vol1.clone()
        result.controlpoints +=   vol2.controlpoints
        result.controlpoints +=   vol3.controlpoints
        result.controlpoints -= 2*vol4.controlpoints
        return result
    else:
        raise ValueError('Requires two or six input surfaces')
Пример #44
0
    def test_insert_knot(self):
        # more or less random 3D volume with p=[2,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 0], [-1, 1, 0], [0, 2, 0], [1, -1, 0], [1, 0, 0], [1, 1, 0],
                         [2, 1, 0], [2, 2, 0], [2, 3, 0], [3, 0, 0], [4, 1, 0], [3, 2, 0],
                         [0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1, 2], [1, 0, 2], [1, 1, 2],
                         [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 1], [4, 1, 1], [3, 2, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, 0.37, 0.44)  # pick some evaluation point (could be anything)

        vol.insert_knot(.20,        0)
        vol.insert_knot( .5,       'u')
        vol.insert_knot( .7,        0)
        vol.insert_knot( .1,        1)
        vol.insert_knot( 1.0 / 3,   1)
        vol.insert_knot( .8,        2)
        vol.insert_knot( .9,       'W')
        knot1, knot2, knot3 = vol.knots(with_multiplicities=True)
        self.assertEqual(len(knot1), 10)  # 7 to start with, 3 new ones
        self.assertEqual(len(knot2), 8)  # 6 to start with, 2 new ones
        self.assertEqual(len(knot3), 6)  # 4 to start with, 2 new ones
        self.assertEqual(vol.controlpoints.shape, (7, 5, 4, 3))

        evaluation_point2 = vol(0.23, 0.37, 0.44)

        # evaluation before and after insert_knot should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])

        # test a rational 3D volume
        controlpoints = [[0, 0, 1, 1], [-1, 1, .96, 1], [0, 2, 1, 1], [1, -1, 1, 1], [1, 0, .8, 1],
                         [1, 1, 1, 1], [2, 1, .89, 1], [2, 2, .9, 1], [2, 3, 1, 1], [3, 0, 1, 1],
                         [4, 1, 1, 1], [3, 2, 1, 1], [0, 0, 1, 2], [-1, 1, .7, 2], [0, 2, 1.3, 2],
                         [1, -1, 1, 2], [1, 0, .77, 2], [1, 1, 1, 2], [2, 1, .89, 1], [2, 2, .8, 4],
                         [2, 3, 1, 1], [3, 0, 1, 1], [4, 1, 1, 1], [3, 2, 1, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints, True)

        evaluation_point1 = vol(0.23, 0.37, 0.44)

        vol.insert_knot([.20, .5, .7], 0)
        vol.insert_knot([.1, 1.0 / 3], 1)
        vol.insert_knot([.8, .9], 2)
        knot1, knot2, knot3 = vol.knots(with_multiplicities=True)
        self.assertEqual(len(knot1), 10)  # 7 to start with, 3 new ones
        self.assertEqual(len(knot2), 8)  # 6 to start with, 2 new ones
        self.assertEqual(len(knot3), 6)  # 4 to start with, 2 new ones
        self.assertEqual(vol.controlpoints.shape, (7, 5, 4, 4))

        evaluation_point2 = vol(0.23, 0.37, 0.44)

        # evaluation before and after RaiseOrder should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])
Пример #45
0
    def test_split(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1, 2], [1, 0, 2], [1, 1, 2],
                         [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0], [4, 1, 0], [3, 2, 0],
                         [0, 0, 3], [-1, 1, 3], [0, 2, 3], [1, -1, 5], [1, 0, 5], [1, 1, 5],
                         [2, 1, 4], [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)
        split_u_vol = vol.split([.1, .2, .3, .4, .5, .6], 0)
        split_v_vol = vol.split(.1, 1)
        split_w_vol = vol.split([.4, .5, .6], 2)

        self.assertEqual(len(split_u_vol), 7)
        self.assertEqual(len(split_v_vol), 2)
        self.assertEqual(len(split_w_vol), 4)

        # check that the u-vector is properly split
        self.assertAlmostEqual(split_u_vol[0].start(0), 0.0)
        self.assertAlmostEqual(split_u_vol[0].end(0),   0.1)
        self.assertAlmostEqual(split_u_vol[1].start(0), 0.1)
        self.assertAlmostEqual(split_u_vol[1].end(0),   0.2)
        self.assertAlmostEqual(split_u_vol[2].start(0), 0.2)
        self.assertAlmostEqual(split_u_vol[2].end(0),   0.3)
        self.assertAlmostEqual(split_u_vol[6].start(0), 0.6)
        self.assertAlmostEqual(split_u_vol[6].end(0),   2.0)
        # check that the other vectors remain unchanged
        self.assertAlmostEqual(split_u_vol[2].start(1), 0.0)
        self.assertAlmostEqual(split_u_vol[2].end(1),   1.0)
        self.assertAlmostEqual(split_u_vol[2].start(2), 0.0)
        self.assertAlmostEqual(split_u_vol[2].end(2),   1.0)
        # check that the v-vector is properly split
        self.assertAlmostEqual(split_v_vol[0].start(1), 0.0)
        self.assertAlmostEqual(split_v_vol[0].end(1),   0.1)
        self.assertAlmostEqual(split_v_vol[1].start(1), 0.1)
        self.assertAlmostEqual(split_v_vol[1].end(1),   1.0)
        # check that the others remain unchanged
        self.assertAlmostEqual(split_v_vol[1].start(0), 0.0)
        self.assertAlmostEqual(split_v_vol[1].end(0),   2.0)
        self.assertAlmostEqual(split_v_vol[1].start(2), 0.0)
        self.assertAlmostEqual(split_v_vol[1].end(2),   1.0)
        # check that the w-vector is properly split
        self.assertAlmostEqual(split_w_vol[1].start(2), 0.4)
        self.assertAlmostEqual(split_w_vol[1].end(2),   0.5)
        self.assertAlmostEqual(split_w_vol[2].start(2), 0.5)
        self.assertAlmostEqual(split_w_vol[2].end(2),   0.6)
        # check that the others remain unchanged
        self.assertAlmostEqual(split_w_vol[1].start(0), 0.0)
        self.assertAlmostEqual(split_w_vol[1].end(0),   2.0)
        self.assertAlmostEqual(split_w_vol[1].start(1), 0.0)
        self.assertAlmostEqual(split_w_vol[1].end(1),   1.0)

        # check that evaluations remain unchanged
        pt1 = vol(0.23, 0.12, 0.3)

        self.assertAlmostEqual(split_u_vol[2].evaluate(.23, .12, .3)[0], pt1[0])
        self.assertAlmostEqual(split_u_vol[2].evaluate(.23, .12, .3)[1], pt1[1])
        self.assertAlmostEqual(split_u_vol[2].evaluate(.23, .12, .3)[2], pt1[2])

        self.assertAlmostEqual(split_v_vol[1].evaluate(.23, .12, .3)[0], pt1[0])
        self.assertAlmostEqual(split_v_vol[1].evaluate(.23, .12, .3)[1], pt1[1])
        self.assertAlmostEqual(split_v_vol[1].evaluate(.23, .12, .3)[2], pt1[2])

        self.assertAlmostEqual(split_w_vol[0].evaluate(.23, .12, .3)[0], pt1[0])
        self.assertAlmostEqual(split_w_vol[0].evaluate(.23, .12, .3)[1], pt1[1])
        self.assertAlmostEqual(split_w_vol[0].evaluate(.23, .12, .3)[2], pt1[2])
Пример #46
0
    def test_reparam(self):
        # identity mapping, control points generated from knot vector
        basis1 = BSplineBasis(4, [2,2,2,2,3,6,7,7,7,7])
        basis2 = BSplineBasis(3, [-3,-3,-3,20,30,31,31,31])
        basis3 = BSplineBasis(5, [0,0,0,0,0,8,8,8,8,8])
        vol = Volume(basis1, basis2, basis3)

        self.assertAlmostEqual(vol.start(0),  2)
        self.assertAlmostEqual(vol.end(0),    7)
        self.assertAlmostEqual(vol.start(1), -3)
        self.assertAlmostEqual(vol.end(1),   31)
        self.assertAlmostEqual(vol.start(2),  0)
        self.assertAlmostEqual(vol.end(2),    8)

        vol.reparam((4,10), (0,9), (2,3))
        self.assertAlmostEqual(vol.start(0),  4)
        self.assertAlmostEqual(vol.end(0),   10)
        self.assertAlmostEqual(vol.start(1),  0)
        self.assertAlmostEqual(vol.end(1),    9)
        self.assertAlmostEqual(vol.start(2),  2)
        self.assertAlmostEqual(vol.end(2),    3)

        vol.reparam((5,11), direction=0)
        self.assertAlmostEqual(vol.start(0),  5)
        self.assertAlmostEqual(vol.end(0),   11)
        self.assertAlmostEqual(vol.start(1),  0)
        self.assertAlmostEqual(vol.end(1),    9)
        self.assertAlmostEqual(vol.start(2),  2)
        self.assertAlmostEqual(vol.end(2),    3)

        vol.reparam((5,11), direction=1)
        self.assertAlmostEqual(vol.start(0),  5)
        self.assertAlmostEqual(vol.end(0),   11)
        self.assertAlmostEqual(vol.start(1),  5)
        self.assertAlmostEqual(vol.end(1),   11)
        self.assertAlmostEqual(vol.start(2),  2)
        self.assertAlmostEqual(vol.end(2),    3)

        vol.reparam((5,11), direction=2)
        self.assertAlmostEqual(vol.start(0),  5)
        self.assertAlmostEqual(vol.end(0),   11)
        self.assertAlmostEqual(vol.start(1),  5)
        self.assertAlmostEqual(vol.end(1),   11)
        self.assertAlmostEqual(vol.start(2),  5)
        self.assertAlmostEqual(vol.end(2),   11)

        vol.reparam((-9,9))
        self.assertAlmostEqual(vol.start(0), -9)
        self.assertAlmostEqual(vol.end(0),    9)
        self.assertAlmostEqual(vol.start(1),  0)
        self.assertAlmostEqual(vol.end(1),    1)
        self.assertAlmostEqual(vol.start(2),  0)
        self.assertAlmostEqual(vol.end(2),    1)

        vol.reparam()
        self.assertAlmostEqual(vol.start(0),  0)
        self.assertAlmostEqual(vol.end(0),    1)
        self.assertAlmostEqual(vol.start(1),  0)
        self.assertAlmostEqual(vol.end(1),    1)
        self.assertAlmostEqual(vol.start(2),  0)
        self.assertAlmostEqual(vol.end(2),    1)

        vol.reparam((4,10), (0,9), (2,7))
        vol.reparam(direction=1)
        self.assertAlmostEqual(vol.start(0),  4)
        self.assertAlmostEqual(vol.end(0),   10)
        self.assertAlmostEqual(vol.start(1),  0)
        self.assertAlmostEqual(vol.end(1),    1)
        self.assertAlmostEqual(vol.start(2),  2)
        self.assertAlmostEqual(vol.end(2),    7)
Пример #47
0
 def test_volume(self):
     v = Volume()
     self.assertAlmostEqual(v.volume(), 1.0)
     v -= (.5, .5, 0)
     v[:,:,1,0:2] = 0.0 # squeeze top together, creating a pyramid
     self.assertAlmostEqual(v.volume(), 1.0/3)