def dither(model, radius=1, use_full=True, x_error=0.0, y_error=0.0, z_error=0.0, error_spread_threshold=0.8, blur=True, mem_use_log=[]): if radius == 0: return VoxelModel.copy(model) if blur: new_model = model.blur(radius) mem_use_log.append(memory_usage_psutil()) new_model = new_model.scaleValues() mem_use_log.append(memory_usage_psutil()) else: new_model = model.scaleValues() mem_use_log.append(memory_usage_psutil()) full_model = toFullMaterials(new_model.voxels, new_model.materials, len(material_properties) + 1) mem_use_log.append(memory_usage_psutil()) full_model = ditherOptimized(full_model, use_full, x_error, y_error, z_error, error_spread_threshold) mem_use_log.append(memory_usage_psutil()) return toIndexedMaterials(full_model, model), mem_use_log
def setModel(self, voxel_model): """ Set the model for a simulation. Models located at positive coordinate values will have their workspace size adjusted to maintain their position in the exported simulation. Models located at negative coordinate values will be shifted to the origin. :param voxel_model: VoxelModel :return: None """ # Fit workspace and union with an empty object at the origin to clear offsets if object is raised self.__model = (VoxelModel.copy(voxel_model).fitWorkspace()) | empty()
modelName = 'joint-2.vox' # modelName = 'tail-holder-1r.vox' # Import model start = time.time() modelIn = VoxelModel.fromVoxFile(modelName) end = time.time() importTime = (end - start) start = time.time() # Rotate to best orientation for printing modelIn = modelIn.rotate90(axis=Axes.Y) # Initialize object to hold result modelResult = VoxelModel.copy(modelIn) # Initialize array for identifying library materials library_materials = np.identity(len(material_properties)) library_materials[0, 0] = 0 a = np.ones((len(material_properties), 1)) a[0, 0] = 0 library_materials = np.hstack((a, library_materials)) # Initialize object to hold inserted components insertedComponents = VoxelModel.emptyLike(modelResult) # Find inserted components for m in range(len(modelIn.materials)): i = np.where(np.equal(library_materials, modelIn.materials[m]).all(1))[0]
tab_template = VoxelModel.fromVoxFile('tab_' + tabDesign + '.vox') # Set tab locations xVals = [79, 46] yVals = [9, 9] rVals = [0, 2] # Generate tabs coupon = coupon.insertTabs(tab_template, xVals, yVals, rVals) if blur: # Blur materials coupon = coupon.blur(blurRadius) coupon = coupon.scaleValues() # Add support features coupon_supported = VoxelModel.copy(coupon) if mold: # Generate mold feature around material 2 # Find all voxels containing <50% material 2 material_vector = np.zeros(len(material_properties) + 1) material_vector[0] = 1 material_vector[3] = 0.5 printed_components = coupon - coupon.setMaterialVector(material_vector) printed_components.materials = np.around(printed_components.materials, 0) printed_components = printed_components.scaleValues() # Find voxels containing >50% material 2 cast_components = coupon.difference(printed_components) # Generate mold body
def thin(model, max_iter): x_len = model.voxels.shape[0] + 4 y_len = model.voxels.shape[1] + 4 z_len = model.voxels.shape[2] + 4 struct = ndimage.generate_binary_structure(3, 3) sphere = np.zeros((5, 5, 5), dtype=np.int32) for x in range(5): for y in range(5): for z in range(5): xd = (x - 2) yd = (y - 2) zd = (z - 2) r = np.sqrt(xd ** 2 + yd ** 2 + zd ** 2) if r < 2.5: sphere[x, y, z] = 1 input_model = VoxelModel(np.zeros((x_len, y_len, z_len), dtype=np.int32), model.materials, model.coords) input_model.voxels[2:-2, 2:-2, 2:-2] = model.voxels new_model = VoxelModel.emptyLike(input_model) for i in tqdm(range(max_iter), desc='Thinning'): # Find exterior voxels interior_voxels = input_model.erode(radius=1, plane=Axes.XYZ, structType=Struct.STANDARD, connectivity=1) exterior_voxels = input_model.difference(interior_voxels) x_len = len(exterior_voxels.voxels[:, 0, 0]) y_len = len(exterior_voxels.voxels[0, :, 0]) z_len = len(exterior_voxels.voxels[0, 0, :]) # Create list of exterior voxel coordinates exterior_coords = [] for x in range(x_len): for y in range(y_len): for z in range(z_len): if exterior_voxels.voxels[x, y, z] != 0: exterior_coords.append([x, y, z]) # Store voxels that must be part of the center line for coords in exterior_coords: x = coords[0] y = coords[1] z = coords[2] if input_model.voxels[x,y,z] != 0: # Get matrix of neighbors n = np.copy(input_model.voxels[x - 2:x + 3, y - 2:y + 3, z - 2:z + 3]) n[n != 0] = 1 # Find V - number of voxels near current along xyz axes Vx = np.sum(n[:, 2, 2]) Vy = np.sum(n[2, :, 2]) Vz = np.sum(n[2, 2, :]) # Subtract sphere n = n - sphere n[n < 1] = 0 # Check if subtraction split model C = ndimage.label(n, structure=struct)[1] # Apply conditions if (C > 1) or (Vx <= 2) or (Vy <= 2) or (Vz <= 2): new_model.voxels[x, y, z] = input_model.voxels[x, y, z] if np.sum(interior_voxels.voxels) < 1: break else: input_model = VoxelModel.copy(interior_voxels) new_model = new_model.union(input_model) return new_model
# Combine components coupon = end1 | center | end2 coupon = coupon.setMaterial(1) # Scaled center newCenterLength = round(centerLength * centerLengthScale) centerCoordsOffset = (center.coords[0] + round( (centerLength - newCenterLength) / 2), center.coords[1], center.coords[2]) center = cuboid((newCenterLength, centerWidth, centerHeight), centerCoordsOffset) center = center.setMaterial(2) coupon = center | coupon coupon_input = VoxelModel.copy(coupon) start = time.time() # Generate transition regions transition_1 = cuboid((blurRadius * res * 2, coupon.voxels.shape[1], coupon.voxels.shape[2]), (center.coords[0] - (blurRadius * res), 0, 0), 3) transition_2 = cuboid( (blurRadius * res * 2, coupon.voxels.shape[1], coupon.voxels.shape[2]), (center.coords[0] - (blurRadius * res) + newCenterLength, 0, 0), 3) transition_regions = transition_1 | transition_2 transition_regions = transition_regions.getComponents() # Generate lattice elements
# Start Application if __name__ == '__main__': app1 = qg.QApplication(sys.argv) min_radius = 3 # min radius that results in a printable structure max_radius = 6 # max radius that results in a viable lattice element # Import Models latticeModel = VoxelModel.fromVoxFile( 'lattice_elements/lattice_element_1_30x30.vox') lattice_size = latticeModel.voxels.shape[0] start = time.time() # Process Model modelResult = VoxelModel.copy(latticeModel) modelResult1 = modelResult.dilateBounded(min_radius) modelResult2 = modelResult.dilateBounded(max_radius) end = time.time() m1Time = (end - start) print(m1Time) # Create Mesh mesh1 = Mesh.fromVoxelModel(modelResult1) mesh2 = Mesh.fromVoxelModel(modelResult2) # Create Plot plot1 = Plot(mesh1) plot1.show()
def __init__(self, voxel_model): """ Initialize a Simulation object with default settings. Models located at positive coordinate values will have their workspace size adjusted to maintain their position in the exported simulation. Models located at negative coordinate values will be shifted to the origin. :param voxel_model: VoxelModel """ # Fit workspace and union with an empty object at the origin to clear offsets if object is raised self.__model = (VoxelModel.copy(voxel_model).fitWorkspace()) | empty() # Simulator ############## # Integration self.__integrator = 0 self.__dtFraction = 1.0 # Damping self.__dampingBond = 1.0 # (0-1) Bulk material damping self.__dampingEnvironment = 0.0001 # (0-0.1) Damping caused by fluid environment # Collisions self.__collisionEnable = False self.__collisionDamping = 1.0 # (0-2) Elastic vs inelastic conditions self.__collisionSystem = 3 self.__collisionHorizon = 3 # Features self.__blendingEnable = False self.__xMixRadius = 0 self.__yMixRadius = 0 self.__zMixRadius = 0 self.__blendingModel = 0 self.__polyExp = 1 self.__volumeEffectsEnable = False # Stop conditions self.__stopConditionType = StopCondition.NONE self.__stopConditionValue = 0.0 # Equilibrium mode self.__equilibriumModeEnable = False # Environment ############ # Boundary conditions self.__bcRegions = [] self.__bcVoxels = [] # Gravity self.__gravityEnable = True self.__gravityValue = -9.81 self.__floorEnable = True # Thermal self.__temperatureEnable = False self.__temperatureBaseValue = 25.0 self.__temperatureVaryEnable = False self.__temperatureVaryAmplitude = 0.0 self.__temperatureVaryPeriod = 0.0 # Sensors ####### self.__sensors = [] # Temperature Controls ####### self.__tempControls = [] # Results ################ self.results = [] self.valueMap = np.zeros_like(voxel_model.voxels, dtype=np.float32)