#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright © 2018 Michael J. Hayford
""" miscellaneous functions for working with numpy vectors and floats
.. Created on Wed May 23 15:27:06 2018
.. codeauthor: Michael J. Hayford
"""
import numpy as np
from numpy.linalg import norm
from math import sqrt, pi, acos
[docs]def normalize(v):
""" return normalized version of input vector v """
length = norm(v)
if length == 0.0:
return v
else:
return v/length
[docs]def distance_sqr_2d(pt0, pt1):
""" return distance squared between 2d points pt0 and pt1 """
return (pt0[0] - pt1[0])**2 + (pt0[1] - pt1[1])**2
[docs]def perpendicular_distance_2d(pt, pt1, pt2):
""" return perpendicular distance of pt from the line between pt1 and pt2
"""
return (((pt2[0] - pt1[0])*(pt1[1] - pt[1])
- (pt1[0] - pt[0])*(pt2[1] - pt1[1]))
/ sqrt(distance_sqr_2d(pt2, pt1)))
[docs]def perpendicular_to_radial(pt, pt2):
""" return perpendicular distance of pt from the line between the origin
and pt2
"""
return (pt[0]*pt2[1] - pt2[0]*pt[1]) / sqrt(pt2[0]**2 + pt2[1]**2)
[docs]def perpendicular_to_line(pt, pt1, pt2):
""" return perpendicular distance of pt from the line between pt1 and pt2
"""
d = perpendicular_distance_2d(pt, pt1, pt2)
return (((pt2[0] - pt1[0])*(pt1[1] - pt[1])
- (pt1[0] - pt[0])*(pt2[1] - pt1[1]))
/ sqrt(distance_sqr_2d(pt2, pt1)))
[docs]def perpendicular_from_origin(pt1, pt2):
""" return perpendicular distance of the origin from the line between
pt1 and pt2
"""
return (((pt2[0] - pt1[0])*(pt1[1]) - (pt1[0])*(pt2[1] - pt1[1]))
/ sqrt(distance_sqr_2d(pt2, pt1)))
[docs]def projected_point_on_line(pt, pt1, pt2):
e1 = pt2 - pt1
e2 = pt - pt1
# get dot product of e1, e2
dot_prod = np.dot(e1, e2)
# get squared length of e1
len_sqr_e1 = e1[0]**2 + e1[1]**2
p = np.array([(pt1[0] + (dot_prod * e1[0]) / len_sqr_e1),
(pt1[1] + (dot_prod * e1[1]) / len_sqr_e1)])
return p
[docs]def projected_point_on_radial_line(pt, radial_pt):
# get dot product of radial_pt, pt
dot_prod = np.dot(radial_pt, pt)
# get squared length of radial_pt
len_sqr = radial_pt[0]**2 + radial_pt[1]**2
p = np.array([(dot_prod * radial_pt[0]) / len_sqr,
(dot_prod * radial_pt[1]) / len_sqr])
return p
[docs]def projected_point_on_radial_line_full(pt, radial_pt):
x_prod = pt[0]*radial_pt[1] - radial_pt[0]*pt[1]
# get dot product of radial_pt, pt
dot_prod = np.dot(radial_pt, pt)
# get squared length of radial_pt
len_sqr = radial_pt[0]**2 + radial_pt[1]**2
p = np.array([(dot_prod * radial_pt[0]) / len_sqr,
(dot_prod * radial_pt[1]) / len_sqr])
dist = x_prod/sqrt(len_sqr)
return p, dist
[docs]def euler2opt(e):
""" convert right-handed euler angles to optical design convention,
i.e. alpha and beta are left-handed
"""
return np.array([-e[0], -e[1], e[2]])
[docs]def isanumber(a):
""" returns true if input a can be converted to floating point number """
try:
float(a)
bool_a = True
except ValueError:
bool_a = False
except TypeError:
bool_a = False
return bool_a
[docs]def transpose(mat):
""" transposes a m x n input list and returns the result """
mat_t = []
for j in range(len(mat[0])):
mat_t.append([mat[i][j] for i in range(len(mat))])
return mat_t
[docs]def circle_intersection_area(ra, rb, d):
""" return the area of the intersection of 2 circles
Args:
ra: radius of first circle
rb: radius of second circle
d: separation of the circles' centers of curvature
Returns:
area of the circle intersection
`Weisstein, Eric W. "Circle-Circle Intersection." From MathWorld--A Wolfram Web
Resource. <http://mathworld.wolfram.com/Circle-CircleIntersection.html>`_
"""
if ra < rb: # sort into ascending order for convenience
r, R = ra, rb
else:
r, R = rb, ra
r2 = r**2
if R >= r + d: # smaller circle contained inside the larger one
return pi*r2
if d > r + R: # circles are completely separated - no overlap
return 0
R2 = R**2
d2 = d**2
# calculate area via eq 14 in the referenced link
p1 = r2*acos((d2 + r2 - R2)/(2*d*r))
p2 = R2*acos((d2 + R2 - r2)/(2*d*R))
p3 = sqrt((-d + r + R)*(d + r - R)*(d - r + R)*(d + r + R))/2
area = p1 + p2 - p3
return area
[docs]def compute_tangent_point_to_circle(CofC, r, pt):
""" return the area of the intersection of 2 circles
Args:
CofC: center of curvature of circle (2d numpy array)
r: radius of circle
pt: 2d numpy array of point outside of circle
Returns:
the 2 tangent points for lines from pt to circle
`gboffi. <https://math.stackexchange.com/users/467357/gboffi>`_
`"How to find the equation of a line, tangent to a circle, that passes
through a given external point." StackExchange (version: 2019-05-30)
<https://math.stackexchange.com/a/3190374>`_
"""
dxdy = pt - CofC
dxdyr = np.array([-dxdy[1], dxdy[0]])
d = sqrt(dxdy[0]**2 + dxdy[1]**2)
if d > r:
rho = r/d
ad = rho**2
bd = rho * sqrt(1 - rho**2)
T1 = CofC + ad*dxdy + bd*dxdyr
T2 = CofC + ad*dxdy - bd*dxdyr
return T1, T2