Source code for cdl.algorithms.coordinates

# 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__ import annotations

import numpy as np


[docs] def circle_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 """ return xc - r, yc, xc + r, yc
[docs] def array_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 - r x_end = xc + r result = np.column_stack((x_start, yc, x_end, yc)).astype(float) return result
[docs] def circle_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) / 2 r = np.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) / 2 return xc, yc, r
[docs] def array_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) / 2 r = np.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) / 2 result = np.column_stack((xc, yc, r)).astype(float) return result
[docs] def ellipse_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 + dya x2, y2, x3, y3 = xc - dxb, yc - dyb, xc + dxb, yc + dyb return x0, y0, x1, y1, x2, y2, x3, y3
[docs] def array_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 + dya x2, y2, x3, y3 = xc - dxb, yc - dyb, xc + dxb, yc + dyb result = np.column_stack((x0, y0, x1, y1, x2, y2, x3, y3)).astype(float) return result
[docs] def ellipse_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) / 2 a = np.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) / 2 b = np.sqrt((x3 - x2) ** 2 + (y3 - y2) ** 2) / 2 theta = np.arctan2(y1 - y0, x1 - x0) return xc, yc, a, b, theta
[docs] def array_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) / 2 a = np.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) / 2 b = np.sqrt((x3 - x2) ** 2 + (y3 - y2) ** 2) / 2 theta = np.arctan2(y1 - y0, x1 - x0) result = np.column_stack((xc, yc, a, b, theta)).astype(float) return result