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))
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))
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())
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))
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])
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])
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')
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')