# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.""".. Coordinates Algorithms (see parent package :mod:`cdl.algorithms`)"""# pylint: disable=invalid-name # Allows short reference names like x, y, ...from__future__importannotationsimportwarningsfromtypingimportLiteralimportnumpyasnp
[docs]defcircle_to_diameter(xc:float,yc:float,r:float)->tuple[float,float,float,float]:"""Convert circle center and radius to X diameter coordinates Args: xc: Circle center X coordinate yc: Circle center Y coordinate r: Circle radius Returns: tuple: Circle X diameter coordinates """returnxc-r,yc,xc+r,yc
[docs]defarray_circle_to_diameter(data:np.ndarray)->np.ndarray:"""Convert circle center and radius to X diameter coordinates (array version) Args: data: Circle center and radius, in the form of a 2D array (N, 3) Returns: Circle X diameter coordinates, in the form of a 2D array (N, 4) """xc,yc,r=data[:,0],data[:,1],data[:,2]x_start=xc-rx_end=xc+rresult=np.column_stack((x_start,yc,x_end,yc)).astype(float)returnresult
[docs]defcircle_to_center_radius(x0:float,y0:float,x1:float,y1:float)->tuple[float,float,float]:"""Convert circle X diameter coordinates to center and radius Args: x0: Diameter start X coordinate y0: Diameter start Y coordinate x1: Diameter end X coordinate y1: Diameter end Y coordinate Returns: tuple: Circle center and radius """xc,yc=(x0+x1)/2,(y0+y1)/2r=np.sqrt((x1-x0)**2+(y1-y0)**2)/2returnxc,yc,r
[docs]defarray_circle_to_center_radius(data:np.ndarray)->np.ndarray:"""Convert circle X diameter coordinates to center and radius (array version) Args: data: Circle X diameter coordinates, in the form of a 2D array (N, 4) Returns: Circle center and radius, in the form of a 2D array (N, 3) """x0,y0,x1,y1=data[:,0],data[:,1],data[:,2],data[:,3]xc,yc=(x0+x1)/2,(y0+y1)/2r=np.sqrt((x1-x0)**2+(y1-y0)**2)/2result=np.column_stack((xc,yc,r)).astype(float)returnresult
[docs]defellipse_to_diameters(xc:float,yc:float,a:float,b:float,theta:float)->tuple[float,float,float,float,float,float,float,float]:"""Convert ellipse center, axes and angle to X/Y diameters coordinates Args: xc: Ellipse center X coordinate yc: Ellipse center Y coordinate a: Ellipse half larger axis b: Ellipse half smaller axis theta: Ellipse angle Returns: Ellipse X/Y diameters (major/minor axes) coordinates """dxa,dya=a*np.cos(theta),a*np.sin(theta)dxb,dyb=b*np.sin(theta),b*np.cos(theta)x0,y0,x1,y1=xc-dxa,yc-dya,xc+dxa,yc+dyax2,y2,x3,y3=xc-dxb,yc-dyb,xc+dxb,yc+dybreturnx0,y0,x1,y1,x2,y2,x3,y3
[docs]defarray_ellipse_to_diameters(data:np.ndarray)->np.ndarray:"""Convert ellipse center, axes and angle to X/Y diameters coordinates (array version) Args: data: Ellipse center, axes and angle, in the form of a 2D array (N, 5) Returns: Ellipse X/Y diameters (major/minor axes) coordinates, in the form of a 2D array (N, 8) """xc,yc,a,b,theta=data[:,0],data[:,1],data[:,2],data[:,3],data[:,4]dxa,dya=a*np.cos(theta),a*np.sin(theta)dxb,dyb=b*np.sin(theta),b*np.cos(theta)x0,y0,x1,y1=xc-dxa,yc-dya,xc+dxa,yc+dyax2,y2,x3,y3=xc-dxb,yc-dyb,xc+dxb,yc+dybresult=np.column_stack((x0,y0,x1,y1,x2,y2,x3,y3)).astype(float)returnresult
[docs]defellipse_to_center_axes_angle(x0:float,y0:float,x1:float,y1:float,x2:float,y2:float,x3:float,y3:float,)->tuple[float,float,float,float,float]:"""Convert ellipse X/Y diameters coordinates to center, axes and angle Args: x0: major axis start X coordinate y0: major axis start Y coordinate x1: major axis end X coordinate y1: major axis end Y coordinate x2: minor axis start X coordinate y2: minor axis start Y coordinate x3: minor axis end X coordinate y3: minor axis end Y coordinate Returns: Ellipse center, axes and angle """xc,yc=(x0+x1)/2,(y0+y1)/2a=np.sqrt((x1-x0)**2+(y1-y0)**2)/2b=np.sqrt((x3-x2)**2+(y3-y2)**2)/2theta=np.arctan2(y1-y0,x1-x0)returnxc,yc,a,b,theta
[docs]defarray_ellipse_to_center_axes_angle(data:np.ndarray)->np.ndarray:"""Convert ellipse X/Y diameters coordinates to center, axes and angle (array version) Args: data: Ellipse X/Y diameters coordinates, in the form of a 2D array (N, 8) Returns: Ellipse center, axes and angle, in the form of a 2D array (N, 5) """x0,y0,x1,y1,x2,y2,x3,y3=(data[:,0],data[:,1],data[:,2],data[:,3],data[:,4],data[:,5],data[:,6],data[:,7],)xc,yc=(x0+x1)/2,(y0+y1)/2a=np.sqrt((x1-x0)**2+(y1-y0)**2)/2b=np.sqrt((x3-x2)**2+(y3-y2)**2)/2theta=np.arctan2(y1-y0,x1-x0)result=np.column_stack((xc,yc,a,b,theta)).astype(float)returnresult
[docs]defcartesian2polar(x:np.ndarray,y:np.ndarray,unit:Literal["rad","deg"]="rad")->tuple[np.ndarray,np.ndarray]:"""Convert Cartesian coordinates to polar coordinates. Args: x: Cartesian x-coordinate. y: Cartesian y-coordinate. unit: Unit of the angle ('rad' or 'deg'). Returns: Polar coordinates (r, theta) where r is the radius and theta is the angle. """assertx.shape==y.shape,"x and y must have the same shape"assertunitin["rad","deg"],"unit must be 'rad' or 'deg'"r=np.sqrt(x**2+y**2)theta=np.arctan2(y,x)ifunit=="deg":theta=np.rad2deg(theta)returnr,theta
[docs]defpolar2cartesian(r:np.ndarray,theta:np.ndarray,unit:Literal["rad","deg"]="rad")->tuple[np.ndarray,np.ndarray]:"""Convert polar coordinates to Cartesian coordinates. Args: r: Polar radius. theta: Polar angle. unit: Unit of the angle ('rad' or 'deg'). Returns: Cartesian coordinates (x, y) where x is the x-coordinate and y is the y-coordinate. .. note:: Negative radius values are not supported. They will be set to 0. """assertr.shape==theta.shape,"r and theta must have the same shape"assertunitin["rad","deg"],"unit must be 'rad' or 'deg'"ifnp.any(r<0):warnings.warn("Negative radius values are not supported. They will be set to 0.")r=np.maximum(r,0)ifunit=="deg":theta=np.deg2rad(theta)x=r*np.cos(theta)y=r*np.sin(theta)returnx,y