def testGridCombine(self): # Construct two grids and add some voxel data to each. aGrid, bGrid = openvdb.FloatGrid(), openvdb.FloatGrid(background=1.0) for width in range(63, 1, -10): aGrid.fill((0, 0, 0), (width,)*3, width) bGrid.fill((0, 0, 0), (width,)*3, 2 * width) # Save a copy of grid A. copyOfAGrid = aGrid.deepCopy() # Combine corresponding values of the two grids, storing the result in grid A. # (Since the grids have the same topology and B's active values are twice A's, # the function computes 2*min(a, 2*a) + 3*max(a, 2*a) = 2*a + 3*(2*a) = 8*a # for active values, and 2*min(0, 1) + 3*max(0, 1) = 2*0 + 3*1 = 3 # for inactive values.) aGrid.combine(bGrid, lambda a, b: 2 * min(a, b) + 3 * max(a, b)) self.assertTrue(bGrid.empty()) # Verify that the resulting grid's values are as expected. for original, combined in zip(copyOfAGrid.iterOnValues(), aGrid.iterOnValues()): self.assertEqual(combined.min, original.min) self.assertEqual(combined.max, original.max) self.assertEqual(combined.depth, original.depth) self.assertEqual(combined.value, 8 * original.value) for original, combined in zip(copyOfAGrid.iterOffValues(), aGrid.iterOffValues()): self.assertEqual(combined.min, original.min) self.assertEqual(combined.max, original.max) self.assertEqual(combined.depth, original.depth) self.assertEqual(combined.value, 3)
def convert_vdb_with_yt(datafilename, outfilename, level, variable_out, log_the_variable=False, variable_tol=None, renorm=True, renorm_box=True, renorm_box_size=10.0): # load your selected data file and grab the data ds = yt.load(datafilename) dd = ds.all_data() all_data = ds.covering_grid(level=level, left_edge=ds.domain_left_edge, dims=ds.domain_dimensions * ds.refine_by**level) # to take the log or to not take the log, that is the question if log_the_variable is True: pointdata = np.log10(all_data[variable_out].v) if variable_tol is not None: variable_tol = np.log10(variable_tol) else: pointdata = (all_data[variable_out].v) # rescale from 0->1 for plotting if renorm: minp = pointdata.min() maxp = pointdata.max() pointdata = (pointdata - minp) / (maxp - minp) if variable_tol is not None: variable_tol = (variable_tol - minp) / (maxp - minp) # take out threshold data -> set to 0 if variable_tol is not None: pointdata[pointdata < variable_tol] = 0.0 # generate vdb domain_box = vdb.FloatGrid() domain_box.background = 0.0 domain_box.copyFromArray(pointdata, ijk=(0, 0, 0), tolerance=0) # rescale to voxel size if renorm_box: vsize = renorm_box_size / float( pointdata.shape[0]) # assumes square box/shifting to x-axis units! domain_box.transform = vdb.createLinearTransform( voxelSize=vsize) # tolist is for formatting #print('Writing vdb file...') outvdbname = outfilename + '_' + variable_out + '_one_level_is_' + str( level).zfill(3) + '.vdb' vdb.write(outvdbname, grids=domain_box) #print('... done with writing vdb file to ' + outvdbname) return outvdbname
def testGridCopy(self): grid = openvdb.FloatGrid() self.assertTrue(grid.sharesWith(grid)) self.assertFalse(grid.sharesWith([])) # wrong type; Grid expected copyOfGrid = grid.copy() self.assertTrue(copyOfGrid.sharesWith(grid)) deepCopyOfGrid = grid.deepCopy() self.assertFalse(deepCopyOfGrid.sharesWith(grid)) self.assertFalse(deepCopyOfGrid.sharesWith(copyOfGrid))
def testMap(self): grid = openvdb.BoolGrid() grid.fill((-4, -4, -4), (5, 5, 5), grid.zeroValue) # make active grid.mapOn(lambda x: not x) # replace active False values with True n = sum(item.value for item in grid.iterOnValues()) self.assertEqual(n, 10 * 10 * 10) grid = openvdb.FloatGrid() grid.fill((-4, -4, -4), (5, 5, 5), grid.oneValue) grid.mapOn(lambda x: x * 2) n = sum(item.value for item in grid.iterOnValues()) self.assertEqual(n, 10 * 10 * 10 * 2) grid = openvdb.Vec3SGrid() grid.fill((-4, -4, -4), (5, 5, 5), grid.zeroValue) grid.mapOn(lambda x: (0, 1, 0)) n = sum(item.value[1] for item in grid.iterOnValues()) self.assertEqual(n, 10 * 10 * 10)
def testGridFill(self): grid = openvdb.FloatGrid() acc = grid.getAccessor() ijk = (1, 1, 1) self.assertRaises(TypeError, lambda: grid.fill("", (7, 7, 7), 1, False)) self.assertRaises(TypeError, lambda: grid.fill( (0, 0, 0), "", 1, False)) self.assertRaises(TypeError, lambda: grid.fill((0, 0, 0), (7, 7, 7), "", False)) self.assertFalse(acc.isValueOn(ijk)) grid.fill((0, 0, 0), (7, 7, 7), 1, active=False) self.assertEqual(acc.getValue(ijk), 1) self.assertFalse(acc.isValueOn(ijk)) grid.fill((0, 0, 0), (7, 7, 7), 2, active=True) self.assertEqual(acc.getValue(ijk), 2) self.assert_(acc.isValueOn(ijk)) activeCount = grid.activeVoxelCount() acc.setValueOn(ijk, 2.125) self.assertEqual(grid.activeVoxelCount(), activeCount) grid.fill(ijk, ijk, 2.125, active=True) self.assertEqual(acc.getValue(ijk), 2.125) self.assert_(acc.isValueOn(ijk)) self.assertEqual(grid.activeVoxelCount(), activeCount) leafCount = grid.leafCount() grid.prune() self.assertAlmostEqual(acc.getValue(ijk), 2.125) self.assert_(acc.isValueOn(ijk)) self.assertEqual(grid.leafCount(), leafCount) self.assertEqual(grid.activeVoxelCount(), activeCount) grid.prune(tolerance=0.2) self.assertEqual(grid.activeVoxelCount(), activeCount) self.assertEqual(acc.getValue(ijk), 2) self.assert_(acc.isValueOn(ijk)) self.assert_(grid.leafCount() < leafCount)
def testTransform(self): xform1 = openvdb.createLinearTransform( [[.5, 0, 0, 0], [0, 1, 0, 0], [0, 0, 2, 0], [1, 2, 3, 1]]) self.assertTrue(xform1.typeName != '') self.assertEqual(xform1.indexToWorld((1, 1, 1)), (1.5, 3, 5)) xform2 = xform1 self.assertEqual(xform2, xform1) xform2 = xform1.deepCopy() self.assertEqual(xform2, xform1) xform2 = openvdb.createFrustumTransform(taper=0.5, depth=100, xyzMin=(0, 0, 0), xyzMax=(100, 100, 100), voxelSize=0.25) self.assertNotEqual(xform2, xform1) worldp = xform2.indexToWorld((10, 10, 10)) worldp = [int(round(x * 1000000)) for x in worldp] self.assertEqual(worldp, [-110000, -110000, 2500000]) grid = openvdb.FloatGrid() self.assertEqual(grid.transform, openvdb.createLinearTransform()) grid.transform = openvdb.createLinearTransform(2.0) self.assertEqual(grid.transform, openvdb.createLinearTransform(2.0))
def testCopyToArray(self): import random import time # Skip this test if NumPy is not available. try: import numpy as np except ImportError: return # Skip this test if the OpenVDB module was built without NumPy support. arr = np.ndarray((1, 2, 1)) grid = openvdb.FloatGrid() try: grid.copyFromArray(arr) except NotImplementedError: return # Verify that a grid can't be copied into a non-three-dimensional array. grid = openvdb.FloatGrid() self.assertRaises(TypeError, lambda: grid.copyToArray('abc')) arr = np.ndarray((1, 2)) self.assertRaises(ValueError, lambda: grid.copyToArray(arr)) # Verify that complex-valued arrays are not supported. arr = np.ndarray((1, 2, 1), dtype = complex) grid = openvdb.FloatGrid() self.assertRaises(TypeError, lambda: grid.copyToArray(arr)) ARRAY_DIM = 201 BG, FG = 0, 1 # Generate some random voxel coordinates. random.seed(0) def randCoord(): return tuple(random.randint(0, ARRAY_DIM-1) for i in range(3)) coords = set(randCoord() for i in range(200)) def createArrays(): # Test both scalar- and vec3-valued (i.e., four-dimensional) arrays. for shape in ( (ARRAY_DIM, ARRAY_DIM, ARRAY_DIM), # scalar array (ARRAY_DIM, ARRAY_DIM, ARRAY_DIM, 3) # vec3 array ): for dtype in (np.float32, np.int32, np.float64, np.int64, np.uint32, np.bool): # Return a new NumPy array. arr = np.ndarray(shape, dtype) arr.fill(-100) yield arr # Test copying from arrays of various types to grids of various types. for cls in openvdb.GridTypes: for arr in createArrays(): isScalarArray = (len(arr.shape) == 3) isScalarGrid = False try: len(cls.zeroValue) # values of vector grids are sequences, which have a length except TypeError: isScalarGrid = True # values of scalar grids have no length gridBG = valueFactory(cls.zeroValue, BG) gridFG = valueFactory(cls.zeroValue, FG) # Create an empty grid, fill it with the background value, # then set some elements to the foreground value. grid = cls(gridBG) acc = grid.getAccessor() for c in coords: acc.setValueOn(c, gridFG) # Verify that scalar grids can't be copied into vector arrays # and vector grids can't be copied into scalar arrays. if isScalarGrid != isScalarArray: self.assertRaises(ValueError, lambda: grid.copyToArray(arr)) continue # Copy values from the grid to the NumPy array. now = time.clock() grid.copyToArray(arr) elapsed = time.clock() - now #print 'copied %d voxels from %s to %s array in %f sec' % ( # arr.shape[0] * arr.shape[1] * arr.shape[2], grid.__class__.__name__, # str(arr.dtype) + ('' if isScalarArray else '[]'), elapsed) # Verify that the grid's active voxels match the array's foreground elements. for c in coords: self.assertEqual(arr[c] if isScalarArray else tuple(arr[c]), gridFG) arr[c] = gridBG self.assertEqual(np.amin(arr), BG) self.assertEqual(np.amax(arr), BG)
argv = sys.argv[1:] if (len(argv) < 2): print("Arguments: <num_frames> <output_dir> [-f(lip y and z)]") exit(0) num_frames = int(argv[0]) out_path = str(argv[1]) flip_y_z = len(argv) > 2 and argv[2] == "-f" # Will look for ordered grid.***** files in dir_path dir_path = os.path.dirname(os.path.realpath(__file__)) dir_path += "/grids" for frame in range(0, num_frames): density_grid = vdb.FloatGrid() density_grid.name = "density" v_grid = vdb.Vec3SGrid() v_grid.name = "v" density_accessor = density_grid.getAccessor() v_accessor = v_grid.getAccessor() filepath = dir_path + "/grid." + str(frame).zfill(5) with open(filepath) as f: for line in f: if (" " in line) and ("[" in line) and ("]" in line) and ("density:" in line): index = line.split(" ")[0].split("[")[1].split("]")[0] i = int(index.split(",")[0])
if not [item for item in ds.field_list if item[1] == variable]: print >> sys.stderr, "ERROR: Invalid field name: " + variable exit() # This is required to be able to write out ghost zones for FLASH data if isFlash: ds.periodicity = (True, True, True) # Iterate through all levels for level in range(minLevel, maxLevel + 1): # Select specific level of grids set from dataset gs = ds.index.select_grids(level) # Initiate OpenVDB FloatGrid maskCube = vdb.FloatGrid() dataCube = vdb.FloatGrid() # Go over all grids in current level for index in range(len(gs)): subGrid = gs[index] # Extract grid (without ghost zone) with specific varible subGridVar = subGrid[variable] # Extract grid (with ghost zone) with specific varible subGridVarWithGZ = subGrid.retrieve_ghost_zones( n_zones=1, fields=variable)[variable] # Take the log (base 10), if needed
import pyopenvdb as vdb import pymeshpotato.mpmesh as mepo import pymeshpotato.mpvolume as mpvol import pymeshpotato.mputils as mputils cube = vdb.FloatGrid() cube.fill(min=(-19, -19, -19), max=(19, 19, 19), value=10.0) sphere1 = vdb.createLevelSetSphere(radius=20, center=(0.0, 0.0, 0.0)) sphere2 = vdb.createLevelSetSphere(radius=20, center=(10.5, 4, 3)) sphere3 = mpvol.ImplicitSphere(1.0, mputils.getMPVec3([0, 0, 0])) volume1 = mpvol.VDBVolumeGrid.ptr(sphere1) volume2 = mpvol.VDBVolumeGrid.ptr(sphere2) volume3 = mpvol.VDBVolumeGrid.ptr(cube) clamp_volume1 = mpvol.Clamp.ptr(volume1, 0, -1) clamp_volume2 = mpvol.Clamp.ptr(volume2, 0, -1) addedVolume = mpvol.AddVolumeFloat.ptr(clamp_volume1, clamp_volume2) #print addedVolume.eval([3,4,5]) #coordbbox = mpvol.CoordBBox( minBB = mpvol.getVDBCoord([-40, -40, -40]) maxBB = mpvol.getVDBCoord([40, 40, 40]) vdbvolume = mpvol.makeVDBGrid(addedVolume, mpvol.getVDBCoordBBox(minBB, maxBB), 0.5) vdbvolume2 = mpvol.makeVDBGrid(sphere3, mpvol.getVDBCoordBBox(minBB, maxBB), 0.05) vdb.write("testVolume.vdb", grids=[vdbvolume, vdbvolume2, cube])
def particles_to_mesh(particles, particle_radius, voxel_size, level): """creates a density grid and then extracts the levelset as quad mesh""" if not particle_radius >= voxel_size: raise ValueError("particle_radius ({}) >= voxel_size ({})".format( particle_radius, voxel_size)) if not voxel_size > 0: raise ValueError("voxel_size ({}) > 0".format(voxel_size)) if not level > 0: raise ValueError("level ({}) > 0".format(level)) import pyopenvdb as vdb from scipy.spatial import cKDTree def kernel(sqr_d, sqr_h): return np.maximum(0, (1 - sqr_d / sqr_h)**3) point_radius = particle_radius / voxel_size points = particles / voxel_size tree = cKDTree(points) grid = vdb.FloatGrid() accessor = grid.getAccessor() visited_indices = set() unvisited_indices = set() visited_points = np.zeros(shape=points.shape[0:1], dtype=np.uint8) def compute_value(ijk): nn = tree.query_ball_point(ijk, point_radius) if nn: sqr_dist = np.sum((points[nn] - np.asarray(ijk))**2, axis=-1) # use negative values to get normals pointing outwards value = -np.sum(kernel(sqr_dist, point_radius**2)) visited_points[nn] = 1 else: value = 0 accessor.setValueOn(ijk, value=value) return value neighbors = np.array([ [-1, 0, 0], [1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1], ], dtype=np.int32) while np.count_nonzero(visited_points) != len(visited_points): unvisited_points_mask = visited_points == 0 idx = tuple(np.round(points[unvisited_points_mask][0]).astype(np.int32)) visited_points[np.argwhere(unvisited_points_mask)[0]] = 1 unvisited_indices.add(idx) while len(unvisited_indices): idx = unvisited_indices.pop() visited_indices.add(idx) value = compute_value(idx) if value: new_indices = neighbors + idx for x in new_indices: i = tuple(x) if not i in visited_indices: unvisited_indices.add(i) # we use negative values to get normals pointing outwards vertices, quads = grid.convertToQuads(isovalue=-level) vertices *= voxel_size return vertices, quads
def testCopyFromArray(self): import random import time # Skip this test if NumPy is not available. try: import numpy as np except ImportError: return # Skip this test if the OpenVDB module was built without NumPy support. arr = np.zeros((1, 2, 1)) grid = openvdb.FloatGrid() try: grid.copyFromArray(arr) except NotImplementedError: return # Verify that a non-three-dimensional array can't be copied into a grid. grid = openvdb.FloatGrid() self.assertRaises(TypeError, lambda: grid.copyFromArray('abc')) arr = np.zeros((1, 2)) self.assertRaises(ValueError, lambda: grid.copyFromArray(arr)) # Verify that complex-valued arrays are not supported. arr = np.zeros((1, 2, 1), dtype=complex) grid = openvdb.FloatGrid() self.assertRaises(TypeError, lambda: grid.copyFromArray(arr)) ARRAY_DIM = 201 BG, FG = 0, 1 # Generate some random voxel coordinates. random.seed(0) def randCoord(): return tuple(random.randint(0, ARRAY_DIM - 1) for i in range(3)) coords = set(randCoord() for i in range(200)) def createArrays(): # Test both scalar- and vec3-valued (i.e., four-dimensional) arrays. for shape in ( (ARRAY_DIM, ARRAY_DIM, ARRAY_DIM), # scalar array (ARRAY_DIM, ARRAY_DIM, ARRAY_DIM, 3) # vec3 array ): for dtype in (np.float32, np.int32, np.float64, np.int64, np.uint32, np.bool): # Create a NumPy array, fill it with the background value, # then set some elements to the foreground value. arr = np.ndarray(shape, dtype) arr.fill(BG) bg = arr[0, 0, 0] for c in coords: arr[c] = FG yield arr # Test copying from arrays of various types to grids of various types. for cls in openvdb.GridTypes: # skip copying test for PointDataGrids if cls.valueTypeName.startswith('ptdataidx'): continue for arr in createArrays(): isScalarArray = (len(arr.shape) == 3) isScalarGrid = False try: len( cls.zeroValue ) # values of vector grids are sequences, which have a length except TypeError: isScalarGrid = True # values of scalar grids have no length gridBG = valueFactory(cls.zeroValue, BG) gridFG = valueFactory(cls.zeroValue, FG) # Create an empty grid. grid = cls(gridBG) acc = grid.getAccessor() # Verify that scalar arrays can't be copied into vector grids # and vector arrays can't be copied into scalar grids. if isScalarGrid != isScalarArray: self.assertRaises(ValueError, lambda: grid.copyFromArray(arr)) continue # Copy values from the NumPy array to the grid, marking # background values as inactive and all other values as active. #now = time.process_time() grid.copyFromArray(arr) #elapsed = time.process_time() - now #print 'copied %d voxels from %s array to %s in %f sec' % ( # arr.shape[0] * arr.shape[1] * arr.shape[2], # str(arr.dtype) + ('' if isScalarArray else '[]'), # grid.__class__.__name__, elapsed) # Verify that the grid's active voxels match the array's foreground elements. self.assertEqual(grid.activeVoxelCount(), len(coords)) for c in coords: self.assertEqual(acc.getValue(c), gridFG) for value in grid.iterOnValues(): self.assertTrue(value.min in coords)
import pyopenvdb as vdb import numpy # Generate a random array of floats array = numpy.random.rand(50, 50, 50) # Copy values from a three-dimensional array of doubles # into a grid of floats. grid = vdb.FloatGrid() print('Copying') grid.copyFromArray(array) assert grid.activeVoxelCount() == array.size print(grid.evalActiveVoxelBoundingBox()) grid.name = 'float' # Write to VDB file vdb.write('floats.vdb', grids=[grid])