math.py
1 """Various math-related functions.""" 2 3 # ruff: noqa: PLR2004 4 5 import math 6 7 8 def weight_from_length(*, length: float, diameter: float, density: float) -> float: 9 """Calculate the weight of a piece of filament. 10 11 Args: 12 length (float): Filament length in mm 13 diameter (float): Filament diameter in mm 14 density (float): Density of filament material in g/cm3 15 16 Returns: 17 float: Weight in g 18 19 """ 20 volume_mm3 = length * math.pi * (diameter / 2) ** 2 21 volume_cm3 = volume_mm3 / 1000 22 return density * volume_cm3 23 24 25 def length_from_weight(*, weight: float, diameter: float, density: float) -> float: 26 """Calculate the length of a piece of filament. 27 28 Args: 29 weight (float): Filament weight in g 30 diameter (float): Filament diameter in mm 31 density (float): Density of filament material in g/cm3 32 33 Returns: 34 float: Length in mm 35 36 """ 37 volume_cm3 = weight / density 38 volume_mm3 = volume_cm3 * 1000 39 return volume_mm3 / (math.pi * (diameter / 2) ** 2) 40 41 42 def rgb_to_lab(rgb: list[int]) -> list[float]: 43 """Convert a RGB color to CIELAB. 44 45 Input is of form [r, g, b] where r, g, and b are integers between 0 and 255. 46 Output is of form [l, a, b] where l, a, and b are floats. 47 """ 48 r, g, b = rgb[0] / 255, rgb[1] / 255, rgb[2] / 255 49 50 r = (r / 12.92) if (r <= 0.04045) else math.pow((r + 0.055) / 1.055, 2.4) 51 g = (g / 12.92) if (g <= 0.04045) else math.pow((g + 0.055) / 1.055, 2.4) 52 b = (b / 12.92) if (b <= 0.04045) else math.pow((b + 0.055) / 1.055, 2.4) 53 54 x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047 55 y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000 56 z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883 57 58 x = math.pow(x, 1 / 3) if (x > 0.008856) else (7.787 * x) + 16 / 116 59 y = math.pow(y, 1 / 3) if (y > 0.008856) else (7.787 * y) + 16 / 116 60 z = math.pow(z, 1 / 3) if (z > 0.008856) else (7.787 * z) + 16 / 116 61 62 return [(116 * y) - 16, 500 * (x - y), 200 * (y - z)] 63 64 65 def delta_e(lab_a: list[float], lab_b: list[float]) -> float: 66 """Calculate the color difference between two CIELAB colors.""" 67 delta_l = lab_a[0] - lab_b[0] 68 delta_a = lab_a[1] - lab_b[1] 69 delta_b = lab_a[2] - lab_b[2] 70 c1 = math.sqrt(lab_a[1] * lab_a[1] + lab_a[2] * lab_a[2]) 71 c2 = math.sqrt(lab_b[1] * lab_b[1] + lab_b[2] * lab_b[2]) 72 delta_c = c1 - c2 73 delta_h = delta_a * delta_a + delta_b * delta_b - delta_c * delta_c 74 delta_h = math.sqrt(delta_h) if delta_h > 0 else 0 75 sc = 1.0 + 0.045 * c1 76 sh = 1.0 + 0.015 * c1 77 delta_l_kl_sl = delta_l / 1.0 78 delta_c_kc_sc = delta_c / sc 79 delta_h_kh_sh = delta_h / sh 80 i = delta_l_kl_sl * delta_l_kl_sl + delta_c_kc_sc * delta_c_kc_sc + delta_h_kh_sh * delta_h_kh_sh 81 return math.sqrt(i) if i > 0 else 0 82 83 84 def hex_to_rgb(hex_code: str) -> list[int]: 85 """Convert a hex color code to RGB. 86 87 Input is of form #RRGGBB where RR, GG, and BB are hexadecimal numbers. 88 Output is of form [r, g, b] where r, g, and b are integers between 0 and 255. 89 """ 90 hex_code = hex_code.lstrip("#") 91 92 r = int(hex_code[0:2], 16) 93 g = int(hex_code[2:4], 16) 94 b = int(hex_code[4:6], 16) 95 96 return [r, g, b]