Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 46 additions & 31 deletions Scripts for Variable Angle/Backtransformation_GCode_var_angle.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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':
Expand All @@ -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)
if __name__ == '__main__':
main()
50 changes: 32 additions & 18 deletions Scripts for Variable Angle/Transformation_STL_var_angle.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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()