diff --git a/Scripts for Variable Angle/Backtransformation_GCode_var_angle.py b/Scripts for Variable Angle/Backtransformation_GCode_var_angle.py index 3cca849..85b7595 100644 --- a/Scripts for Variable Angle/Backtransformation_GCode_var_angle.py +++ b/Scripts for Variable Angle/Backtransformation_GCode_var_angle.py @@ -1,20 +1,39 @@ -import re import numpy as np import time +import argparse -# ----------------------------------------------------------------------------------------- -# Transformation Settings -# ----------------------------------------------------------------------------------------- -FILE_NAME = 'tower_01_B.gcode' # filename including extension -FOLDER_NAME = 'gcodes/' # name of the subfolder in which the gcode is located -CONE_ANGLE = 16 # transformation angle -CONE_TYPE = 'outward' # type of the cone: 'inward' & 'outward' -FIRST_LAYER_HEIGHT = 0.2 # moves all the gcode up to this height. Use also for stacking -X_SHIFT = 110 # moves your gcode away from the origin into the center of the bed (usually bed size / 2) -Y_SHIFT = 90 +def main(): + args = parseArgs() + starttime = time.time() + backtransform_file(path=args.src.name, output=args.dst.name, cone_type=args.coneType, maximal_length=0.5, angle_comp='radial', x_shift=args.xshift, y_shift=args.yshift, + cone_angle_deg=args.angle, z_desired=args.firstLayerHeight, e_parallel=0, e_perpendicular=0) + endtime = time.time() + print('GCode translated, time used:', endtime - starttime) -def insert_Z(row, z_value): + +def parseArgs(): + parser = argparse.ArgumentParser(description='Backtransforms gcode file generated from a transformed STL.') + + DEF_ANGLE = 16.0 + DEF_CONE_TYPE = 'outward' + DEF_FIRST_LAYER_HEIGHT = 0.2 + DEF_XSHIFT = 125.0 + DEF_YSHIFT = 125.0 + + parser.add_argument('-s', '--src', dest='src', help='Input file path.', required=True, type=argparse.FileType('r')) + parser.add_argument('-d', '--dst', dest='dst', help='Output file path.', required=True, type=argparse.FileType('w')) + parser.add_argument('-a', '--angle', dest='angle', help=f'Transformation angle, default {DEF_ANGLE}.', default=DEF_ANGLE, type=float) + parser.add_argument('-t', '--type', dest='coneType', help=f'Type of the cone. Default {DEF_CONE_TYPE}.', default=DEF_CONE_TYPE, type=str, choices=['outward', 'inward']) + parser.add_argument('-l', '--height', dest='firstLayerHeight', help=f'Moves all the gcode up to this height. Use also for stacking. Default {DEF_FIRST_LAYER_HEIGHT}', type=float, default=DEF_FIRST_LAYER_HEIGHT) + parser.add_argument('-x', '--xshift', dest='xshift', help='Moves gcode away from the origin to the center of the bed (bed size / 2). Default {DEF_XSHIFT}', type=float, default=DEF_XSHIFT) + parser.add_argument('-y', '--yshift', dest='yshift', help='Moves gcode away from the origin to the center of the bed (bed size / 2). Default {DEF_YSHIFT}', type=float, default=DEF_YSHIFT) + + args = parser.parse_args() + return args + + +def insert_Z(row: str, z_value: float) -> str: """ Insert or replace the z-value in a row. The new z-value must be given. :param row: string @@ -43,7 +62,7 @@ def insert_Z(row, z_value): return row_new -def replace_E(row, dist_old, dist_new, corr_value): +def replace_E(row: str, dist_old: float, dist_new: float, corr_value: float) -> str: """ Replace the amount of extruded filament in a row. The new amount is proportional to the old amount, where the factor is obtained by the ratio of new distance to old distance. (wuem: Due to the transformation, the amount has to be @@ -73,7 +92,7 @@ def replace_E(row, dist_old, dist_new, corr_value): return row_new -def compute_angle_radial(x_old, y_old, x_new, y_new, inward_cone): +def compute_angle_radial(x_old: float, y_old: float, x_new: float, y_new: float, inward_cone: bool) -> float: """ Compute the angle of the printing head, when moving from an old point [x_old, y_old] to a new point [x_new, y_new]. (Note: the z-value is not considered for the orientation of the printing head.) The direction is given by the @@ -98,9 +117,6 @@ def compute_angle_radial(x_old, y_old, x_new, y_new, inward_cone): return angle - - - def compute_U_values(angle_array): """ Compute the U-values, which will be inserted, according to given angle values. @@ -123,7 +139,7 @@ def compute_U_values(angle_array): return angle_insert -def insert_U(row, angle): +def insert_U(row: str, angle: float) -> str: """ Insert or replace the U-value in a row, where the U-values describes the orientation of the printing head. :param row: string @@ -146,7 +162,7 @@ def insert_U(row, angle): return row_new -def backtransform_data_radial(data, cone_type, maximal_length, cone_angle_rad): +def backtransform_data_radial(data: list, cone_type: str, maximal_length: float, cone_angle_rad: float) -> list: """ Backtransform GCode, which is given in a list, each element describing a row. Rows which describe a movement are detected, x-, y-, z-, E- and U-values are replaced accordingly to the transformation. If a original segment @@ -262,7 +278,7 @@ def backtransform_data_radial(data, cone_type, maximal_length, cone_angle_rad): -def translate_data(data, cone_type, translate_x, translate_y, z_desired, e_parallel, e_perpendicular): +def translate_data(data: list, cone_type: str, translate_x: float, translate_y: float, z_desired:float , e_parallel: float, e_perpendicular: float) -> list: """ Translate the GCode in x- and y-direction. Only the lines, which describe a movement will be translated. Additionally, if z_translation is True, the z-values will be translated such that the minimal z-value is z_desired. @@ -333,11 +349,12 @@ def translate_data(data, cone_type, translate_x, translate_y, z_desired, e_paral return new_data -def backtransform_file(path, cone_type, maximal_length, angle_comp, x_shift, y_shift, cone_angle_deg, z_desired, e_parallel, e_perpendicular): +def backtransform_file(path: str, output:str , cone_type: str, maximal_length: float, angle_comp: str, x_shift: float, y_shift: float, cone_angle_deg: int, z_desired: float, e_parallel: float, e_perpendicular: float) -> None: """ Read GCode from file, backtransform and translate it. :param path: string String with the path to the GCode-file + :param output: string :param cone_type: string String, either 'outward' or 'inward', defines which transformation should be used :param maximal_length: float @@ -358,7 +375,7 @@ def backtransform_file(path, cone_type, maximal_length, angle_comp, x_shift, y_s Error perpendicular to nozzle :return: None """ - + cone_angle_rad = cone_angle_deg / 180 * np.pi if angle_comp == 'radial': @@ -372,17 +389,15 @@ def backtransform_file(path, cone_type, maximal_length, angle_comp, x_shift, y_s data_bt = translate_data(data_bt, cone_type, x_shift, y_shift, z_desired, e_parallel, e_perpendicular) data_bt_string = ''.join(data_bt) - path_write = re.sub(r'gcodes', 'gcodes_backtransformed', path) - path_write = re.sub(r'.gcode', '_bt_' + cone_type + '_' + angle_comp + '.gcode', path_write) - print(path_write) - with open(path_write, 'w+') as f_gcode_bt: + # path_write = re.sub(r'gcodes', 'gcodes_backtransformed', path) + # path_write = re.sub(r'.gcode', '_bt_' + cone_type + '_' + angle_comp + '.gcode', path_write) + # print(path_write) + # with open(path_write, 'w+') as f_gcode_bt: + with open(output, 'w+') as f_gcode_bt: f_gcode_bt.write(data_bt_string) print('File successfully backtransformed and translated.') return None -starttime = time.time() -backtransform_file(path=FOLDER_NAME + FILE_NAME, cone_type=CONE_TYPE, maximal_length=0.5, angle_comp='radial', x_shift=X_SHIFT, y_shift=Y_SHIFT, - cone_angle_deg=CONE_ANGLE, z_desired=FIRST_LAYER_HEIGHT, e_parallel=0, e_perpendicular=0) -endtime = time.time() -print('GCode translated, time used:', endtime - starttime) \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/Scripts for Variable Angle/Transformation_STL_var_angle.py b/Scripts for Variable Angle/Transformation_STL_var_angle.py index 09b16b2..acaa947 100644 --- a/Scripts for Variable Angle/Transformation_STL_var_angle.py +++ b/Scripts for Variable Angle/Transformation_STL_var_angle.py @@ -1,26 +1,43 @@ import numpy as np from stl import mesh import time +import argparse +def main(): -#----------------------------------------------------------------------------------------- -# Transformation Settings -#----------------------------------------------------------------------------------------- + args = parseArgs() -FILE_NAME = 'tower_01_-20' # Filename without extension -FOLDER_NAME_UNTRANSFORMED = 'stl/' -FOLDER_NAME_TRANSFORMED = 'stl_transformed/' # Make sure this folder exists -CONE_ANGLE = 16 # Transformation angle -REFINEMENT_ITERATIONS = 1 # refinement iterations of the stl. 2-3 is a good start for regular stls. If its already uniformaly fine, use 0 or 1. High number cause huge models and long script runtimes -TRANSFORMATION_TYPE = 'outward' # type of the cone: 'inward' & 'outward' + startTime = time.time() + transformed_STL = transformation_STL_file(path=args.src.name, cone_type=args.coneType, cone_angle_deg=args.angle, nb_iterations=args.iterations) + transformed_STL.save(args.dst.name) + deltaTime = time.time() - startTime + print(f'Transformation time: {deltaTime}') +def parseArgs(): + parser = argparse.ArgumentParser(description='Transform STL 3D models for conical slicing.') -def transformation_kegel(points, cone_angle_rad, cone_type): + DEF_ANGLE = 16.0 + DEF_CONE_TYPE = 'outward' + DEF_ITEREATIONS = 2 + + parser.add_argument('-s', '--src', dest='src', help='Input file path', required=True, type=argparse.FileType('r')) + parser.add_argument('-d', '--dst', dest='dst', help='Output file path', required=True, type=argparse.FileType('w')) + parser.add_argument('-a', '--angle', dest='angle', help=f'Transformation angle. Defaut {DEF_ANGLE}.', default=DEF_ANGLE, type=float) + parser.add_argument('-t', '--type', dest='coneType', help=f'Type of the cone. Default {DEF_CONE_TYPE}.', default=DEF_CONE_TYPE, type=str, choices=['outward', 'inward']) + parser.add_argument('-i', '--iterations', dest='iterations', help=f'Refinement iterations of the STL. 2-3 for regular STLs. Use 0 or 1 if uniformally fine. Large numbers cause huge models and long runtimes. Default {DEF_ITEREATIONS}.', type=int, default=DEF_ITEREATIONS) + + args = parser.parse_args() + + return args + +def transformation_kegel(points, cone_angle_rad: float, cone_type: str): """ Computes the cone-transformation (x', y', z') = (x / cos(angle), y / cos(angle), z + \sqrt{x^{2} + y^{2}} * tan(angle)) for a list of points :param points: array array of points of shape ( , 3) + :param cone_angle_rad: float + TODO: description missing :param cone_type: string String, either 'outward' or 'inward', defines which transformation should be used :return: array @@ -59,7 +76,7 @@ def refinement_four_triangles(triangle): return np.array([triangle1, triangle2, triangle3, triangle4]) -def refinement_triangulation(triangle_array, num_iterations): +def refinement_triangulation(triangle_array, num_iterations: int): """ Compute a refinement of a triangulation using the refinement_four_triangles function. The number of iteration defines, how often the triangulation has to be refined; n iterations lead to @@ -78,14 +95,14 @@ def refinement_triangulation(triangle_array, num_iterations): return refined_array -def transformation_STL_file(path, cone_type, cone_angle_deg, nb_iterations): +def transformation_STL_file(path: str, cone_type: str, cone_angle_deg: float, nb_iterations: int): """ Read a stl-file, refine the triangulation and transform it according to the cone-transformation :param path: string path to the stl file :param cone_type: string String, either 'outward' or 'inward', defines which transformation should be used - :param cone_angle: int + :param cone_angle_deg: float angle to transform the part :param nb_iterations: int number of iterations, the triangulation should be refined before the transformation @@ -104,8 +121,5 @@ def transformation_STL_file(path, cone_type, cone_angle_deg, nb_iterations): my_mesh_transformed = mesh.Mesh(my_mesh_transformed) return my_mesh_transformed -startzeit = time.time() -transformed_STL = transformation_STL_file(path=FOLDER_NAME_UNTRANSFORMED + FILE_NAME + '.stl', cone_type=TRANSFORMATION_TYPE, cone_angle_deg=CONE_ANGLE, nb_iterations=REFINEMENT_ITERATIONS) -transformed_STL.save(FOLDER_NAME_TRANSFORMED + FILE_NAME + '_' + TRANSFORMATION_TYPE + '_' + str(CONE_ANGLE) + 'deg_transformed.stl') -endzeit = time.time() -print('Transformation time:', endzeit - startzeit) +if __name__ == '__main__': + main()