Source code for golding_mso.math_calc

"""
This module provides functions for geometric and mathematical calculations.
"""

import math
from typing import overload


[docs] def get_line_from_points( point1: tuple[float, float], point2: tuple[float, float] ) -> tuple[float, float]: """ Calculate the slope and y-intercept of a line given two points. Parameters ---------- point1 : tuple Coordinates of the first point (x, y). point2 : tuple Coordinates of the second point (x, y). Returns ------- m : float Slope of the line. b : float Y-intercept of the line. """ xdiff = point1[0] - point2[0] ydiff = point1[1] - point2[1] m = ydiff / xdiff if xdiff != 0 else float("inf") # slope b = point1[1] - m * point1[0] # y-intercept return m, b
[docs] def dist_from_line(line: tuple[float, float], point: tuple[float, float]) -> float: """ Calculates the distance from a point to a line defined by its slope and y-intercept. The line is defined in the x-y plane, and the point is a 2D point (x, y). Parameters ---------- line : tuple Slope (m) and y-intercept (b) of the line. point : tuple Coordinates of the point (x, y). Returns ------- distance : float Perpendicular distance from the point to the line. """ x0, y0 = point m, b = line b_perp = y0 + m * x0 m_perp = -m if m == float("inf"): # Vertical line case return abs(point[0] - b) elif m == 0: return abs(point[1] - b) else: # Distance from point (x0, y0) to line y = mx + b x1 = (m_perp * x0 + b_perp - b) / m y1 = m * x1 + b return math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
[docs] def define_xy_line( point1: tuple[float, float], point2: tuple[float, float], point3: tuple[float, float], ) -> tuple[float, float]: """ Defines a line in 3D space using two points and a third point to determine the plane. Returns the slope (m) and y-intercept (b) of the line in the x-y plane. Parameters ---------- point1 : tuple Coordinates of the first point (x, y, z). point2 : tuple Coordinates of the second point (x, y, z). point3 : tuple Coordinates of the third point (x, y, z) used to define the plane. Returns ------- m : float Slope of the line in the x-y plane. b : float Y-intercept of the line in the x-y plane. """ xdiff = point1[0] - point2[0] ydiff = point1[1] - point2[1] if xdiff == 0: m = -float("inf") # vertical line b = None else: m = -xdiff / ydiff b = point3[1] - m * point3[0] return m, b
@overload def perpendicular_distance_point_to_line( line: tuple[float, float], point: tuple[float, float], ) -> float: x0, y0 = point m, b = line x1, y1 = (0, b) x2, y2 = (1, m + b) @overload def perpendicular_distance_point_to_line( line: tuple[tuple[float, float], tuple[float, float]], point: tuple[float, float], ) -> float: x0, y0 = point x1, y1 = line[0] x2, y2 = line[1]
[docs] def perpendicular_distance_point_to_line(line, point) -> float: """ Calculate the perpendicular distance from a point to a line defined by two points. This function uses the cross product method for accurate distance calculation and handles all edge cases including vertical and horizontal lines. Parameters ---------- point : tuple Coordinates of the point (x, y). line_point1 : tuple Coordinates of the first point defining the line (x, y). line_point2 : tuple Coordinates of the second point defining the line (x, y). Returns ------- distance : float Perpendicular distance from the point to the line. Raises ------ ValueError: If the two line points are identical (cannot define a line). """ if ( isinstance(line, tuple) and len(line) == 2 and all(isinstance(pt, tuple) and len(pt) == 2 for pt in line) ): x0, y0 = point x1, y1 = line[0] x2, y2 = line[1] else: x0, y0 = point m, b = line x1, y1 = (0, b) x2, y2 = (1, m + b) # Check if line points are identical if x1 == x2 and y1 == y2: raise ValueError("Line points cannot be identical - unable to define a line") # Calculate perpendicular distance using cross product formula # |((x2-x1)(y1-y0) - (x1-x0)(y2-y1))| / sqrt((x2-x1)^2 + (y2-y1)^2) numerator = abs((x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1)) denominator = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) return numerator / denominator
[docs] def perpendicular_distance_point_to_line_3d( point: tuple[float, float, float], line_point1: tuple[float, float, float], line_point2: tuple[float, float, float], ) -> float: """ Calculate the perpendicular distance from a point to a line in 3D space. Uses vector cross product to find the shortest distance from a point to a line defined by two points in 3D space. Parameters ---------- point : tuple Coordinates of the point (x, y, z). line_point1 : tuple Coordinates of the first point defining the line (x, y, z). line_point2 : tuple Coordinates of the second point defining the line (x, y, z). Returns ------- distance : float Perpendicular distance from the point to the line in 3D space. Raises ------ ValueError: If the two line points are identical (cannot define a line). """ x0, y0, z0 = point x1, y1, z1 = line_point1 x2, y2, z2 = line_point2 # Check if line points are identical if x1 == x2 and y1 == y2 and z1 == z2: raise ValueError("Line points cannot be identical - unable to define a line") # Vector from line_point1 to line_point2 (direction vector) d = (x2 - x1, y2 - y1, z2 - z1) # Vector from line_point1 to point w = (x0 - x1, y0 - y1, z0 - z1) # Cross product w × d cross_product = ( w[1] * d[2] - w[2] * d[1], # i component w[2] * d[0] - w[0] * d[2], # j component w[0] * d[1] - w[1] * d[0], # k component ) # Magnitude of cross product cross_magnitude = math.sqrt( cross_product[0] ** 2 + cross_product[1] ** 2 + cross_product[2] ** 2 ) # Magnitude of direction vector d_magnitude = math.sqrt(d[0] ** 2 + d[1] ** 2 + d[2] ** 2) return cross_magnitude / d_magnitude
[docs] def distance3D(a: tuple[float, float, float], b: tuple[float, float, float]) -> float: """ Calculates the Euclidean distance between two 3D points. Parameters ---------- a : tuple Coordinates of the first point (x, y, z). b : tuple Coordinates of the second point (x, y, z). Returns ------- distance : float Euclidean distance between the two points. """ distance = abs( math.sqrt(((a[0] - b[0]) ** 2) + ((a[1] - b[1]) ** 2) + ((a[2] - b[2]) ** 2)) ) return distance