def main(): compas_mesh = Mesh.from_obj(os.path.join(DATA, MODEL)) delta = get_param({}, key='delta', defaults_type='gcode') # boolean for delta printers print_volume_x = get_param({}, key='print_volume_x', defaults_type='gcode') # in mm print_volume_y = get_param({}, key='print_volume_y', defaults_type='gcode') # in mm if delta: move_mesh_to_point(compas_mesh, Point(0, 0, 0)) else: move_mesh_to_point(compas_mesh, Point(print_volume_x / 2, print_volume_y / 2, 0)) # ----- slicing slicer = PlanarSlicer(compas_mesh, slicer_type="cgal", layer_height=4.5) slicer.slice_model() generate_brim(slicer, layer_width=3.0, number_of_brim_offsets=4) simplify_paths_rdp_igl(slicer, threshold=0.6) seams_smooth(slicer, smooth_distance=10) slicer.printout_info() save_to_json(slicer.to_data(), OUTPUT_DIR, 'slicer_data.json') # ----- print organization print_organizer = PlanarPrintOrganizer(slicer) print_organizer.create_printpoints() # Set fabrication-related parameters set_extruder_toggle(print_organizer, slicer) print_organizer.printout_info() # create and output gcode gcode_parameters = {} # leave all to default gcode_text = print_organizer.output_gcode(gcode_parameters) utils.save_to_text_file(gcode_text, OUTPUT_DIR, 'my_gcode.gcode')
def get_layer_ppts(self, layer, base_boundary): """ Creates the PrintPoints of a single layer.""" max_layer_height = get_param(self.parameters, key='max_layer_height', defaults_type='layers') min_layer_height = get_param(self.parameters, key='min_layer_height', defaults_type='layers') avg_layer_height = get_param(self.parameters, 'avg_layer_height', 'layers') all_pts = [pt for path in layer.paths for pt in path.points] closest_fks, projected_pts = utils.pull_pts_to_mesh_faces( self.slicer.mesh, all_pts) normals = [ Vector(*self.slicer.mesh.face_normal(fkey)) for fkey in closest_fks ] count = 0 crv_to_check = Path( base_boundary.points, True) # creation of fake path for the lower boundary layer_ppts = {} for i, path in enumerate(layer.paths): layer_ppts['path_%d' % i] = [] for p in path.points: cp = closest_point_on_polyline(p, Polyline(crv_to_check.points)) d = distance_point_point(cp, p) ppt = PrintPoint(pt=p, layer_height=avg_layer_height, mesh_normal=normals[count]) ppt.closest_support_pt = Point(*cp) ppt.distance_to_support = d ppt.layer_height = max(min(d, max_layer_height), min_layer_height) ppt.up_vector = Vector( *normalize_vector(Vector.from_start_end(cp, p))) ppt.frame = ppt.get_frame() layer_ppts['path_%d' % i].append(ppt) count += 1 crv_to_check = path return layer_ppts
def generate_paths(self): """ Generates isocontours. """ start_domain, end_domain = min(self.scalar_field), max( self.scalar_field) step = (end_domain - start_domain) / (self.no_of_isocurves + 1) max_dist = get_param(self.parameters, key='vertical_layers_max_centroid_dist', defaults_type='layers') vertical_layers_manager = VerticalLayersManager(max_dist) # create paths + layers with progressbar.ProgressBar(max_value=self.no_of_isocurves) as bar: for i in range(0, self.no_of_isocurves + 1): for vkey, data in self.mesh.vertices(data=True): if i == 0: data['scalar_field'] = self.scalar_field[ vkey] - 0.05 * step # things can be tricky in the edge else: data['scalar_field'] = self.scalar_field[ vkey] - i * step contours = ScalarFieldContours(self.mesh) contours.compute() contours.add_to_vertical_layers_manager( vertical_layers_manager) bar.update(i) # advance progress bar self.layers = vertical_layers_manager.layers
def generate_paths(self): """ Generates isocontours. """ paths_type = 'flat' # 'spiral' # 'zigzag' v_left, v_right = 0.0, 1.0 - 1e-5 max_dist = get_param(self.parameters, key='vertical_layers_max_centroid_dist', defaults_type='layers') vertical_layers_manager = VerticalLayersManager(max_dist) # create paths + layers with progressbar.ProgressBar(max_value=self.no_of_isocurves) as bar: for i in range(0, self.no_of_isocurves + 1): if i == 0: i += 0.05 # contours are a bit tricky in the edges if paths_type == 'spiral': u1, u2 = i, i + 1.0 else: # 'flat' u1 = u2 = i p1 = (u1, v_left) p2 = (u2, v_right) contours = UVContours(self.mesh, p1, p2) contours.compute() contours.add_to_vertical_layers_manager( vertical_layers_manager) bar.update(i) # advance progress bar self.layers = vertical_layers_manager.layers
def topological_sorting(self): """ When the print consists of various paths, this function initializes a class that creates a directed graph with all these parts, with the connectivity of each part reflecting which other parts it lies on, and which other parts lie on it.""" max_layer_height = get_param(self.parameters, key='max_layer_height', defaults_type='layers') self.topo_sort_graph = topo_sort.SegmentsDirectedGraph( self.slicer.mesh, self.vertical_layers, max_layer_height, DATA_PATH=self.DATA_PATH)
def create_compound_targets(self): """ Creates the target_LOW and the target_HIGH and computes the geodesic distances. """ # --- low target geodesics_method = get_param(self.parameters, key='target_LOW_geodesics_method', defaults_type='interpolation_slicing') method, params = 'min', [ ] # no other union methods currently supported for lower target self.target_LOW = CompoundTarget(self.mesh, 'boundary', 1, self.DATA_PATH, union_method=method, union_params=params, geodesics_method=geodesics_method) # --- high target geodesics_method = get_param(self.parameters, key='target_HIGH_geodesics_method', defaults_type='interpolation_slicing') method, params = get_union_method(self.parameters) self.target_HIGH = CompoundTarget(self.mesh, 'boundary', 2, self.DATA_PATH, union_method=method, union_params=params, geodesics_method=geodesics_method) # --- uneven boundaries of high target self.target_HIGH.offset = get_param( self.parameters, key='uneven_upper_targets_offset', defaults_type='interpolation_slicing') self.target_HIGH.compute_uneven_boundaries_weight_max(self.target_LOW) # --- save intermediary get_distance outputs self.target_LOW.save_distances("distances_LOW.json") self.target_HIGH.save_distances("distances_HIGH.json")
def get_union_method(params_dict): """ Read input params_dict and return union method id and its parameters. target_type: LOW/HIGH """ smooth_union_data = get_param(params_dict, key='target_HIGH_smooth_union', defaults_type='interpolation_slicing') chamfer_union_data = get_param(params_dict, key='target_HIGH_chamfer_union', defaults_type='interpolation_slicing') stairs_union_data = get_param(params_dict, key='target_HIGH_stairs_union', defaults_type='interpolation_slicing') if smooth_union_data[0]: method = 'smooth' params = smooth_union_data[1] assert not chamfer_union_data[0] and not stairs_union_data[ 0], 'You can only select one union method.' assert len(params) == 1, 'Wrong number of union params' return method, params elif chamfer_union_data[0]: method = 'chamfer' params = chamfer_union_data[1] assert not smooth_union_data[0] and not stairs_union_data[ 0], 'You can only select one union method.' assert len(params) == 1, 'Wrong number of union params' return method, params elif stairs_union_data[0]: method = 'stairs' params = stairs_union_data[1] assert not smooth_union_data[0] and not chamfer_union_data[ 0], 'You can only select one union method.' assert len(params) == 2, 'Wrong number of union params' return method, params else: method = 'min' params = [] return method, params
def create_printpoints(self): """ Create the print points of the fabrication process Based on the directed graph, select one topological order. From each path collection in that order copy PrintPoints dictionary in the correct order. """ current_layer_index = 0 # (1) --- First add the printpoints of the horizontal brim layer (first layer of print) self.printpoints_dict['layer_0'] = {} if len(self.horizontal_layers) > 0: # first add horizontal brim layers paths = self.horizontal_layers[0].paths for j, path in enumerate(paths): self.printpoints_dict['layer_0']['path_%d' % j] = \ [PrintPoint(pt=point, layer_height=get_param(self.parameters, 'avg_layer_height', 'layers'), mesh_normal=utils.get_normal_of_path_on_xy_plane(k, point, path, self.slicer.mesh)) for k, point in enumerate(path.points)] current_layer_index += 1 # (2) --- Select order of vertical layers if len(self.vertical_layers ) > 1: # the you need to select one topological order all_orders = self.topo_sort_graph.get_all_topological_orders() self.selected_order = all_orders[ 0] # TODO: add more elaborate selection strategy else: self.selected_order = [ 0 ] # there is only one segment, only this option # (3) --- Then create the printpoints of all the vertical layers in the selected order for index, i in enumerate(self.selected_order): layer = self.vertical_layers[i] self.printpoints_dict['layer_%d' % current_layer_index] = {} self.printpoints_dict['layer_%d' % current_layer_index] = self.get_layer_ppts( layer, self.base_boundaries[i]) current_layer_index += 1
def create_printpoints(self): """ Create the print points of the fabrication process """ count = 0 logger.info('Creating print points ...') with progressbar.ProgressBar(max_value=self.slicer.number_of_points) as bar: for i, layer in enumerate(self.slicer.layers): self.printpoints_dict['layer_%d' % i] = {} for j, path in enumerate(layer.paths): self.printpoints_dict['layer_%d' % i]['path_%d' % j] = [] for k, point in enumerate(path.points): normal = utils.get_normal_of_path_on_xy_plane(k, point, path, self.slicer.mesh) h = get_param(self.parameters, 'avg_layer_height', defaults_type='layers') printpoint = PrintPoint(pt=point, layer_height=h, mesh_normal=normal) self.printpoints_dict['layer_%d' % i]['path_%d' % j].append(printpoint) bar.update(count) count += 1 # transfer gradient information to printpoints transfer_mesh_attributes_to_printpoints(self.slicer.mesh, self.printpoints_dict) # add non-planar print data to printpoints for i, layer in enumerate(self.slicer.layers): layer_key = 'layer_%d' % i for j, path in enumerate(layer.paths): path_key = 'path_%d' % j for pp in self.printpoints_dict[layer_key][path_key]: grad_norm = pp.attributes['gradient_norm'] grad = pp.attributes['gradient'] pp.distance_to_support = grad_norm pp.layer_height = grad_norm pp.up_vector = Vector(*normalize_vector(grad)) pp.frame = pp.get_frame()