Source code for gcodeBuddy.misc_functions

import sys
import numpy as np


[docs]def unit_convert(value, current_units, needed_units): """ converts given value to specified units :param value: numerical value to convert :type value: int, float :param current_units: current units of value :type current_units: str :param needed_units: units to convert value to :type needed_units: str :returns: value in requisite units :rtype: int, float Supported Units: Position: "mm", "cm", "m", "in", "ft" \n Speed: "mm/sec", "mm/min", "cm/sec", "cm/min", "m/sec", "m/min", "in/sec", "in/min", "ft/sec", "ft/min" \n Acceleration: Coming soon. \n """ err_msg = "Error in misc_functions.unit_convert(): " if not isinstance(value, (int, float)): print(err_msg + "Argument 'value' of non-int/non-float type") sys.exit(1) if not isinstance(current_units, str): print(err_msg + "Argument 'current_units' of non-string type") sys.exit(1) if not isinstance(needed_units, str): print(err_msg + "Argument 'needed_units' of non-string type") sys.exit(1) units = ( ("mm", "cm", "m", "in", "ft"), # distance ("mm/sec", "mm/min", "cm/sec", "cm/min", "m/sec", "m/min", "in/sec", "in/min", "ft/sec", "ft/min"), # speed () # acceleration ) unit_vals = ( (1000.0, 100.0, 1.0, 39.37, 3.281), # distance (1000.0, 60000.0, 100.0, 6000.0, 1.0, 60.0, 39.37, 2362.0, 3.280, 196.9), # speed () # acceleration ) current_units = current_units.lower() needed_units = needed_units.lower() for i in range(3): # iterating through categories if current_units in units[i] and needed_units in units[i]: # if both units in same category return value * ((unit_vals[i][units[i].index(needed_units)]) / (unit_vals[i][units[i].index(current_units)])) # perform calculation # point will be reached if units aren't in same category print(err_msg + "Unrecognized units passed in argument 'current_units' or 'needed_units'")
[docs]def angle(center_point, end_point): """ returns angle between line formed by two points and +x direction :param center_point: point to be considered as the origin :type center_point: list[int, float], tuple(int, float) :param end_point: point to form line with the relative origin point :type end_point: list[int, float], tuple(int, float) :return: angle between line and +x axis, relative to origin point (degrees) :rtype: float """ err_msg = "Error in misc_functions.angle(): " # error checking if isinstance(center_point, (list, tuple)): if len(center_point) == 2: valid_types = True for coord in center_point: if not isinstance(coord, (int, float)): valid_types = False if not valid_types: print(err_msg + "Element in argument 'center_point' of non-int/non-float type") sys.exit(1) else: print(err_msg + "Argument 'center_point' not of length 2") sys.exit(1) else: print(err_msg + "Argument 'center_point' of non-list/non-tuple type") sys.exit(1) if isinstance(end_point, (list, tuple)): if len(end_point) == 2: valid_types = True for coord in end_point: if not isinstance(coord, (int, float)): valid_types = False if not valid_types: print(err_msg + "Element in argument 'end_point' of non-int/non-float type") sys.exit(1) else: print(err_msg + "Argument 'end_point' not of length 2") sys.exit(1) else: print(err_msg + "Argument 'end_point' of non-list/non-tuple type") sys.exit(1) # establishing end point relative to center rel_point = [end_point[0] - center_point[0], end_point[1] - center_point[1]] if abs(rel_point[0]) < 0.001: # approximate 0, floats aren't real (point on y-axis) if rel_point[1] > 0: return 90.0 else: return 270.0 elif abs(rel_point[1]) < 0.001: # approximate 0, floats suck (point on x-axis) if rel_point[0] > 0: return 0.0 else: return 180.0 if rel_point[0] > 0 and rel_point[1] > 0: # quadrant I return np.arctan(rel_point[1] / rel_point[0]) * (180 / np.pi) elif rel_point[0] < 0 and rel_point[1] > 0: # quadrant II return (np.arctan(-rel_point[0] / rel_point[1]) * (180 / np.pi)) + 90 elif rel_point[0] < 0 and rel_point[1] > 0: # quadrant III return (np.arctan(rel_point[1] / rel_point[0]) * (180 / np.pi)) + 180 else: # quadrant IV return (np.arctan(-rel_point[0] / rel_point[1]) * (180 / np.pi)) + 270
[docs]def centers_from_params(point_a, point_b, radius): """ returns two possible center positions of an arc given two points on arc and a radius :param point_a: one of two distinct points on arc :type point_a: list[int, float], tuple(int, float) :param point_b: one of two distinct points on arc :type point_b: list[int, float], tuple(int, float) :param radius: radius of arc :type radius: int, float :return: two possible center point values :rtype: list[list[int, float]] """ err_msg = "Error in misc_functions.center(): " # error checking point_a if isinstance(point_a, (tuple, list)): if len(point_a) == 2: valid_types = True for coord in point_a: if not isinstance(coord, (int, float)): valid_types = False if not valid_types: print(err_msg + "Element in argument 'point_a' of non-int/non-float type") sys.exit(1) else: print(err_msg + "Argument 'point_a' not of length 2") sys.exit(1) else: print(err_msg + "Argument 'point_a' of non-list/non-tuple type") sys.exit(1) # error checking point_b if isinstance(point_b, (tuple, list)): if len(point_b) == 2: valid_types = True for coord in point_b: if not isinstance(coord, (int, float)): valid_types = False if not valid_types: print(err_msg + "Element in argument 'point_b' of non-int/non-float type") sys.exit(1) else: print(err_msg + "Argument 'point_b' not of length 2") sys.exit(1) else: print(err_msg + "Argument 'point_b' of non-list/non-tuple type") sys.exit(1) # error checking radius if not isinstance(radius, (float, int)): print(err_msg + "Argument 'radius' of non-int/non-float type") # easier variables x_a, y_a = point_a x_b, y_b = point_b r = radius # error checking values if (np.sqrt((x_a - x_b)**2 + (y_a - y_b)**2) / 2) > r: print(err_msg + "Unable to create circle from given points and radius (d_ab > 2r)") sys.exit(1) # sequential computing for readability ret_val_1, ret_val_2 = (0, 0), (0, 0) if np.abs(x_a - x_b) < 0.001 and np.abs(y_a - y_b) < 0.001: # same point print(err_msg + "Arguments 'point_a' and 'point_b' describe the same point and cannot define an arc") sys.exit(1) elif np.abs(x_a - x_b) < 0.001: # points form vertical line y_m = (y_a + y_b) / 2 s_h = np.sqrt(r**2 - (y_a - y_m)**2) ret_val_1 = [x_a + s_h, y_m] ret_val_2 = [x_a - s_h, y_m] elif np.abs(y_a - y_b) < 0.001: # points form horizontal line x_m = (x_a + x_b) / 2 s_v = np.sqrt(r**2 - (x_m - x_a)**2) ret_val_1 = [x_m, y_a + s_v] ret_val_2 = [x_m, y_a - s_v] else: # establishing situation - determining orientation of the rhombus formed by to ret_vals and given coords x_right, y_right = 0, 0 x_left, y_left = 0, 0 if x_a > x_b: # x_a is on right x_right, y_right = x_a, y_a x_left, y_left = x_b, y_b else: # x_b on right x_right, y_right = x_b, y_b x_left, y_left = x_a, y_a # setting parameters x_m = (x_right + x_left) / 2 y_m = (y_right + y_left) / 2 l_1 = (np.sqrt((x_right - x_left)**2 + (y_right - y_left)**2)) / 2 l_1_x = (x_right - x_left) / 2 l_1_y = (y_right - y_left) / 2 l_2 = np.sqrt(r**2 - l_1**2) l_2_x = abs(l_1_y * (l_2 / l_1)) l_2_y = abs(l_1_x * (l_2 / l_1)) # using previous info to find centers: if y_left > y_right: # centerline points up to the right ret_val_1 = [round(x_m + l_2_x, 2), round(y_m + l_2_y, 2)] ret_val_2 = [round(x_m - l_2_x), round(y_m - l_2_y, 2)] else: # centerline points up to the left ret_val_1 = [round(x_m - l_2_x, 2), round(y_m + l_2_y, 2)] ret_val_2 = [round(x_m + l_2_x, 2), round(y_m - l_2_y, 2)] return [ret_val_1, ret_val_2]