def dual_contour(data, res, dims, coarse_level): # Compute vertices dc_verts = [] vindex = {} for x, y, z in it.product(np.arange(dims['xmin'], dims['xmax'], res), np.arange(dims['ymin'], dims['ymax'], res), np.arange(dims['zmin'], dims['zmax'], res)): o = np.array([float(x), float(y), float(z)]) cube_signs = [] # Get signs for cube for v in cube_verts: position = (o + v * res) key = tuple(position) c = True if key in data: c = data[key] > 0 cube_signs.append(c) if all(cube_signs) or not any(cube_signs): continue # Estimate hermite data h_data = [] for e in cube_edges: if cube_signs[e[0]] != cube_signs[e[1]]: h_data.append(estimate_hermite(data, o + cube_verts[e[0]] * res, o + cube_verts[e[1]] * res)) counter = 0 v = np.array([0.0, 0.0, 0.0]) for p in h_data: v += np.array(p) counter += 1 v /= 1.0 * counter # Throw out failed solutions if la.norm(v - o) > 2 * res: continue # Emit one vertex per every cube that crosses vindex[tuple(o)] = len(dc_verts) dc_verts.append(v) # Construct faces dc_quads = [] for x, y, z in it.product(np.arange(dims['xmin'], dims['xmax'], res), np.arange(dims['ymin'], dims['ymax'], res), np.arange(dims['zmin'], dims['zmax'], res)): if not (x, y, z) in vindex: continue # Emit one edge per each edge that crosses o = np.array([float(x), float(y), float(z)]) for i in range(3): for j in range(i): if tuple(o + res * dirs[i]) in vindex and tuple(o + res * dirs[j]) in vindex and tuple( o + res * (dirs[i] + dirs[j])) in vindex: k = 3 - (i + j) # normal id c = True d = True key_ij = tuple(o + res * dirs[i] + res * dirs[j]) key_ijk = tuple(o + res * dirs[i] + res * dirs[j] + res * dirs[k]) if key_ij in data: c = data[key_ij] > 0 if key_ijk in data: d = data[key_ijk] > 0 if c != d: dc_quads.append([vindex[tuple(o)], vindex[tuple(o + res * dirs[i])], vindex[tuple(o + res * dirs[i] + res * dirs[j])], vindex[tuple(o + res * dirs[j])]]) if coarse_level: dc_verts, dc_quads = resolve_manifold_edges(dc_verts, vindex, dc_quads, data, res) return np.array(dc_verts), dc_quads
def dual_contour(dataset, res_fine, is_coarse_level, do_manifold_treatment): """ Applies the dual contouring algorithm to the dataset :param dataset: input dataset :param res_fine: resolution of the finest level :param is_coarse_level: bool gives information whether this is the coarse level :param do_manifold_treatment: bool states whether manifold edges should be resolved :return: vertices, quads and manifold edges """ # Compute vertices dc_verts = [] vindex = {} res = dataset._resolution print "+ generating vertices +" voxel_count = 0 voxel_total = dataset.get_total_voxels() number_of_cube_verts = np.size(cube_verts, 0) for x, y, z in dataset.get_grid_iterator(): if voxel_count % ((voxel_total + 100) / 100) == 0: print "%d%% generating vertices: processing voxel %d of %d." % ( 100 * voxel_count / voxel_total, voxel_count, voxel_total) voxel_count += 1 o = np.array([float(x), float(y), float(z)]) cube_signs = np.zeros(number_of_cube_verts, dtype=bool) # Get signs for cube for i in range(number_of_cube_verts): position = (o + cube_verts[i, :] * res) key = tuple(position) cube_signs[i] = dataset[key] if all(cube_signs) or not any(cube_signs): continue # Estimate hermite data h_data = [] for e in cube_edges: if cube_signs[e[0]] != cube_signs[e[1]]: h_data.append( estimate_hermite(dataset, o + cube_verts[e[0]] * res, o + cube_verts[e[1]] * res, res, res_fine)) counter = 0 v = np.array([0.0, 0.0, 0.0]) for p in h_data: v += np.array(p) counter += 1 v /= 1.0 * counter # Emit one vertex per every cube that crosses vindex[tuple(o)] = len(dc_verts) dc_verts.append(v) dc_quads = [] if is_coarse_level: # Construct faces print "+ generating faces +" voxel_count = 0 for x, y, z in dataset.get_grid_iterator(): if voxel_count % ((voxel_total + 100) / 100) == 0: print "%d%% generating faces: processing voxel %d of %d." % ( 100 * voxel_count / voxel_total, voxel_count, voxel_total) voxel_count += 1 if not (x, y, z) in vindex: continue # Emit one edge per each edge that crosses o = np.array([float(x), float(y), float(z)]) for i in range(3): for j in range(i): if tuple(o + res * dirs[i]) in vindex and \ tuple(o + res * dirs[j]) in vindex and \ tuple(o + res * (dirs[i] + dirs[j])) \ in vindex: k = 3 - (i + j) # normal id c = True d = True key_ij = tuple(o + res * dirs[i] + res * dirs[j]) key_ijk = tuple(o + res * dirs[i] + res * dirs[j] + res * dirs[k]) if dataset.point_is_inside(key_ij): c = dataset[key_ij] if dataset.point_is_inside(key_ijk): d = dataset[key_ijk] if c != d: dc_quads.append([vindex[tuple(o)], vindex[tuple(o + res * dirs[i])], vindex[tuple(o + res * dirs[i] + res * dirs[j])], vindex[tuple(o + res * dirs[j])]]) dc_manifold_edges = [] if do_manifold_treatment: print "+ manifold treatment +" dc_verts, dc_quads, dc_manifold_edges, not_resolved_edges = resolve_manifold_edges(dc_verts, vindex, dc_quads, dataset) else: dc_manifold_edges = [] not_resolved_edges = [] return np.array(dc_verts), np.array(dc_quads), dc_manifold_edges, not_resolved_edges