Source code for pymead.core.constraint_equations

from collections import namedtuple

import numpy as np


[docs] def measure_distance(x1: float, y1: float, x2: float, y2: float): return np.hypot(x1 - x2, y1 - y2)
[docs] def measure_abs_angle(x1: float, y1: float, x2: float, y2: float): return (np.arctan2(y2 - y1, x2 - x1)) % (2 * np.pi)
[docs] def measure_rel_angle3(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): return (np.arctan2(y1 - y2, x1 - x2) - np.arctan2(y3 - y2, x3 - x2)) % (2 * np.pi)
[docs] def measure_rel_angle4(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float): return (np.arctan2(y4 - y3, x4 - x3) - np.arctan2(y2 - y1, x2 - x1)) % (2 * np.pi)
[docs] def measure_point_line_distance_signed(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): """ Measures the signed distance from a point :math:`(x_3, y_3)` to a line defined by two points: :math:`(x_1, y_1)` and :math:`(x_2, y_2)`. This signed version is used in the point-line symmetry constraint because a perpendicular constraint does not necessarily prevent the GCS from moving the symmetric point to the same side of the line as the target point. Parameters ---------- x1: float x-coordinate of the line's start point y1: float y-coordinate of the line's start point x2: float x-coordinate of the line's end point y2: float y-coordinate of the line's end point x3: float x-coordinate of the target point y3: float y-coordinate of the target point Returns ------- float Distance from the target point to the line """ return ((x2 - x1) * (y1 - y3) - (x1 - x3) * (y2 - y1)) / measure_distance(x1, y1, x2, y2)
[docs] def measure_point_line_distance_unsigned(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): return np.abs(measure_point_line_distance_signed(x1, y1, x2, y2, x3, y3))
[docs] def measure_radius_of_curvature_bezier(Lt: float, Lc: float, n: int, psi: float): return np.abs(np.true_divide(Lt ** 2, Lc * (1 - 1 / n) * np.sin(psi)))
[docs] def measure_curvature_length_bezier(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, R: float, n: int): Lt = measure_distance(x1, y1, x2, y2) psi = measure_rel_angle3(x1, y1, x2, y2, x3, y3) with np.errstate(divide="ignore"): Lc = np.abs(np.true_divide(Lt ** 2, R * (1 - 1 / n) * np.sin(psi))) return Lc
[docs] def measure_curvature_bezier(Lt: float, Lc: float, n: int, psi: float): with np.errstate(divide="ignore"): kappa = np.abs(np.true_divide(Lc * (1 - 1 / n) * np.sin(psi), Lt ** 2)) return kappa
[docs] def measure_data_bezier_curve_joint(xy: np.ndarray, n: np.ndarray): phi1 = measure_abs_angle(xy[2, 0], xy[2, 1], xy[1, 0], xy[1, 1]) phi2 = measure_abs_angle(xy[2, 0], xy[2, 1], xy[3, 0], xy[3, 1]) theta1 = measure_abs_angle(xy[1, 0], xy[1, 1], xy[0, 0], xy[0, 1]) theta2 = measure_abs_angle(xy[3, 0], xy[3, 1], xy[4, 0], xy[4, 1]) psi1 = theta1 - phi1 psi2 = theta2 - phi2 phi_rel = (phi1 - phi2) % (2 * np.pi) Lt1 = measure_distance(xy[1, 0], xy[1, 1], xy[2, 0], xy[2, 1]) Lt2 = measure_distance(xy[2, 0], xy[2, 1], xy[3, 0], xy[3, 1]) Lc1 = measure_distance(xy[0, 0], xy[0, 1], xy[1, 0], xy[1, 1]) Lc2 = measure_distance(xy[3, 0], xy[3, 1], xy[4, 0], xy[4, 1]) kappa1 = measure_curvature_bezier(Lt1, Lc1, n[0], psi1) kappa2 = measure_curvature_bezier(Lt2, Lc2, n[1], psi2) with np.errstate(divide="ignore"): R1 = np.true_divide(1, kappa1) R2 = np.true_divide(1, kappa2) n1 = n[0] n2 = n[1] field_names = ["phi1", "phi2", "theta1", "theta2", "psi1", "psi2", "phi_rel", "Lt1", "Lt2", "Lc1", "Lc2", "kappa1", "kappa2", "R1", "R2", "n1", "n2"] BezierCurveJointData = namedtuple("BezierCurveJointData", field_names=field_names) data = BezierCurveJointData(phi1=phi1, phi2=phi2, theta1=theta1, theta2=theta2, psi1=psi1, psi2=psi2, phi_rel=phi_rel, Lt1=Lt1, Lt2=Lt2, Lc1=Lc1, Lc2=Lc2, kappa1=kappa1, kappa2=kappa2, R1=R1, R2=R2, n1=n1, n2=n2) return data
[docs] def radius_of_curvature_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, R: float, n: int): Lt = measure_distance(x1, y1, x2, y2) psi = measure_rel_angle3(x1, y1, x2, y2, x3, y3) Lc = np.abs(np.true_divide(Lt ** 2, R * (1 - 1 / n) * np.sin(psi))) return distance_constraint(x2, y2, x3, y3, Lc)
[docs] def empty_constraint_weak(): return 0.0
[docs] def fixed_param_constraint(p_val: float, val: float): return p_val - val
[docs] def fixed_param_constraint_weak(new_val: float, old_val: float): return new_val - old_val
[docs] def fixed_x_constraint(x: float, val: float): return x - val
[docs] def fixed_x_constraint_weak(x_new: float, x_old: float): return x_new - x_old
[docs] def fixed_y_constraint(y: float, val: float): return y - val
[docs] def fixed_y_constraint_weak(y_new: float, y_old: float): return y_new - y_old
[docs] def distance_constraint(x1: float, y1: float, x2: float, y2: float, dist: float): return measure_distance(x1, y1, x2, y2) - dist
[docs] def distance_constraint_weak(x1_new: float, y1_new: float, x2_new: float, y2_new: float, x1_old: float, y1_old: float, x2_old: float, y2_old: float): return (measure_distance(x1_new, y1_new, x2_new, y2_new) - measure_distance(x1_old, y1_old, x2_old, y2_old))
[docs] def abs_angle_constraint(x1: float, y1: float, x2: float, y2: float, angle: float): return measure_abs_angle(x1, y1, x2, y2) - angle
[docs] def abs_angle_constraint_weak(x1_new: float, y1_new: float, x2_new: float, y2_new: float, x1_old: float, y1_old: float, x2_old: float, y2_old: float): return (measure_abs_angle(x1_new, y1_new, x2_new, y2_new) - measure_abs_angle(x1_old, y1_old, x2_old, y2_old))
[docs] def rel_angle3_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, angle: float): return measure_rel_angle3(x1, y1, x2, y2, x3, y3) - angle
[docs] def rel_angle3_constraint_weak(x1_new: float, y1_new: float, x2_new: float, y2_new: float, x3_new: float, y3_new: float, x1_old: float, y1_old: float, x2_old: float, y2_old: float, x3_old: float, y3_old: float): return (measure_rel_angle3(x1_new, y1_new, x2_new, y2_new, x3_new, y3_new) - measure_rel_angle3(x1_old, y1_old, x2_old, y2_old, x3_old, y3_old))
[docs] def rel_angle4_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float, angle: float): return measure_rel_angle4(x1, y1, x2, y2, x3, y3, x4, y4) - angle
[docs] def perp3_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): return measure_rel_angle3(x1, y1, x2, y2, x3, y3) - (np.pi / 2)
[docs] def perp4_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float): return measure_rel_angle4(x1, y1, x2, y2, x3, y3, x4, y4) - (np.pi / 2)
[docs] def antiparallel3_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): return measure_rel_angle3(x1, y1, x2, y2, x3, y3) - np.pi
[docs] def antiparallel4_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float): return measure_rel_angle4(x1, y1, x2, y2, x3, y3, x4, y4) - np.pi
[docs] def parallel3_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): return measure_rel_angle3(x1, y1, x2, y2, x3, y3)
[docs] def parallel4_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float): return measure_rel_angle4(x1, y1, x2, y2, x3, y3, x4, y4)
[docs] def point_on_line_constraint(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float): return (y1 - y2) * (x3 - x1) - (y3 - y1) * (x1 - x2)
[docs] def points_equidistant_from_line_constraint_unsigned(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float): return (measure_point_line_distance_unsigned(x1, y1, x2, y2, x3, y3) - measure_point_line_distance_unsigned(x1, y1, x2, y2, x4, y4))
[docs] def points_equidistant_from_line_constraint_signed(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float): return (measure_point_line_distance_signed(x1, y1, x2, y2, x3, y3) + measure_point_line_distance_signed(x1, y1, x2, y2, x4, y4))