Context: Based on the code we can find here, an API to control to control Niryo's robots pyniryo/vision/image_functions:l120.
Return orientation of a contour according to the smallest side in order to be well oriented for gripper
This refactoring produces the desired output and is written by me.
I added type narrowing of the return type to radians in order to give more information on the semantic value of the return value, i.e., to prevent further mix with values that are expected to be degree, for example.
I understand that this style or practices might be disgraceful to some, so I'm looking for feedback and arguments against my code so I can improve.
import collections.abc import math import typing import cv2 import numpy as np Radians = typing.NewType("Radians", float) def radians(x) -> Radians: return Radians(math.radians(x)) def get_contour_angle(contour: collections.abc.Sequence[np.ndarray]) -> Radians: _, (width, height), angle = cv2.minAreaRect(contour) near_square_ratio = 1.25 > (width / height) > 0.75 if near_square_ratio and angle < -45: return radians(angle + 90) if near_square_ratio: return radians(angle) if angle > 0: return radians(angle - 90) if width < height: return radians(angle + 180) return radians(angle + 90) Some argued that the firsts two if should be nested, but I think that the result makes the "what happens" of the top if far from the condition, making it a little bit (I'm not saying "a lot") to contextualize, compared to the flat version.
if near_square_ratio: if angle < -45: return radians(angle + 90) return radians(angle) For me, the benefit is too small compared to the mental cost of the pattern.
A ternary expression could be used, or even multiplication of 90 by boolean, but those alternatives don't find their grace into my eyes (yet?).
if near_square_ratio: return radians(angle if angle >= -45 else angle + 90) # Or if near_square_ratio: return radians(angle + 90 * (angle < -45))
get_contour_anglebe called repeatedly? If so can you show the outer loop? \$\endgroup\$