def find_nearest_points(ray0, ray1): """ Find the nearest points on given rays with respect to the other ray. Parameters ---------- ray0 : ndarray A ray. ray1 : ndarray A ray. Returns ---------- c0 : ndarray Closest point on ray0. c1 : ndarray Closest point on ray1. """ p0 = ray0[0].reshape(3, ) d0 = ray0[1].reshape(3, ) p1 = ray1[0].reshape(3, ) d1 = ray1[1].reshape(3, ) n = np.cross(d0, d1) if np.all(n) == 0: point, distances = calculate_intersection_of_two_rays(ray0, ray1) c0 = c1 = point else: n0 = np.cross(d0, n) n1 = np.cross(d1, n) c0 = p0 + (np.dot((p1 - p0), n1) / np.dot(d0, n1)) * d0 c1 = p1 + (np.dot((p0 - p1), n0) / np.dot(d1, n0)) * d1 return c0, c1
def linearpolarizer(field, rotation=0): """ Definition that represents a linear polarizer. Parameters ---------- field : ndarray Polarization vector of an input beam. rotation : float Represents rotation of the polarizer along propagation direction in angles (couter-clockwise). Returns ---------- result : ndarray Polarization vector of an output beam. """ rotation = np.radians(rotation) rotmat = np.array([[float(np.cos(rotation)), float(np.sin(rotation))], [float(-np.sin(rotation)), float(np.cos(rotation))]]) linearpolarizer = np.array([[1, 0], [0, 0]]) linearpolarizer = np.dot(rotmat.transpose(), np.dot(linearpolarizer, rotmat)) result = np.dot(linearpolarizer, field) return result
def closest_point_to_a_ray(point, ray): """ Definition to calculate the point on a ray that is closest to given point. Parameters ---------- point : list Given point in X,Y,Z. ray : ndarray Given ray. Returns --------- closest_point : ndarray Calculated closest point. """ from odak.raytracing import propagate_a_ray if len(ray.shape) == 2: ray = ray.reshape((1, 2, 3)) p0 = ray[:, 0] p1 = propagate_a_ray(ray, 1.) if len(p1.shape) == 2: p1 = p1.reshape((1, 2, 3)) p1 = p1[:, 0] p1 = p1.reshape(3) p0 = p0.reshape(3) point = point.reshape(3) closest_distance = -np.dot((p0 - point), (p1 - p0)) / np.sum((p1 - p0)**2) closest_point = propagate_a_ray(ray, closest_distance)[0] return closest_point
def same_side(p1, p2, a, b): """ Definition to figure which side a point is on with respect to a line and a point. See http://www.blackpawn.com/texts/pointinpoly/ for more. If p1 and p2 are on the sameside, this definition returns True. Parameters ---------- p1 : list Point(s) to check. p2 : list This is the point check against. a : list First point that forms the line. b : list Second point that forms the line. """ ba = np.subtract(b, a) p1a = np.subtract(p1, a) p2a = np.subtract(p2, a) cp1 = np.cross(ba, p1a) cp2 = np.cross(ba, p2a) test = np.dot(cp1, cp2) if len(p1.shape) > 1: return test >= 0 if test >= 0: return True return False
def calculate_intersection_of_two_rays(ray0, ray1): """ Definition to calculate the intersection of two rays. Parameters ---------- ray0 : ndarray A ray. ray1 : ndarray A ray. Returns ---------- point : ndarray Point in X,Y,Z. distances : ndarray Distances. """ A = np.array([[float(ray0[1][0]), float(ray1[1][0])], [float(ray0[1][1]), float(ray1[1][1])], [float(ray0[1][2]), float(ray1[1][2])]]) B = np.array([ ray0[0][0] - ray1[0][0], ray0[0][1] - ray1[0][1], ray0[0][2] - ray1[0][2] ]) distances = np.linalg.lstsq(A, B)[0] if np.allclose(np.dot(A, distances), B) == False: distances = np.array([0, 0]) distances = distances[np.argsort(-distances)] point = propagate_a_ray(ray0, distances[0])[0] return point, distances
def intersect_w_surface(ray, points): """ Definition to find intersection point inbetween a surface and a ray. For more see: http://geomalgorithms.com/a06-_intersect-2.html Parameters ---------- ray : ndarray A vector/ray. points : ndarray Set of points in X,Y and Z to define a planar surface. Returns ---------- normal : ndarray Surface normal at the point of intersection. distance : float Distance in between starting point of a ray with it's intersection with a planar surface. """ points = np.asarray(points) normal = get_triangle_normal(points) if len(ray.shape) == 2: ray = ray.reshape((1, 2, 3)) if len(points) == 2: points = points.reshape((1, 3, 3)) if len(normal.shape) == 2: normal = normal.reshape((1, 2, 3)) f = normal[:, 0] - ray[:, 0] distance = np.dot(normal[:, 1], f.T) / np.dot(normal[:, 1], ray[:, 1].T) n = np.int(np.amax(np.array([ray.shape[0], normal.shape[0]]))) normal = np.zeros((n, 2, 3)) normal[:, 0] = ray[:, 0] + distance.T * ray[:, 1] distance = np.abs(distance) if normal.shape[0] == 1: normal = normal.reshape((2, 3)) distance = distance.reshape((1)) if distance.shape[0] == 1 and len(distance.shape) > 1: distance = distance.reshape((distance.shape[1])) return normal, distance
def rotate_point(point,angles=[0,0,0],mode='XYZ',origin=[0,0,0],offset=[0,0,0]): """ Definition to rotate a given point. Note that rotation is always with respect to 0,0,0. Parameters ---------- point : ndarray A point. angles : list Rotation angles in degrees. mode : str Rotation mode determines ordering of the rotations at each axis. There are XYZ,YXZ,ZXY and ZYX modes. origin : list Reference point for a rotation. offset : list Shift with the given offset. Returns ---------- result : ndarray Result of the rotation rotx : ndarray Rotation matrix along X axis. roty : ndarray Rotation matrix along Y axis. rotz : ndarray Rotation matrix along Z axis. """ point = np.asarray(point) point -= np.asarray(origin) rotx = rotmatx(angles[0]) roty = rotmaty(angles[1]) rotz = rotmatz(angles[2]) if mode == 'XYZ': result = np.dot(rotz,np.dot(roty,np.dot(rotx,point))) elif mode == 'XZY': result = np.dot(roty,np.dot(rotz,np.dot(rotx,point))) elif mode == 'YXZ': result = np.dot(rotz,np.dot(rotx,np.dot(roty,point))) elif mode == 'ZXY': result = np.dot(roty,np.dot(rotx,np.dot(rotz,point))) elif mode == 'ZYX': result = np.dot(rotx,np.dot(roty,np.dot(rotz,point))) result += np.asarray(origin) result += np.asarray(offset) return result,rotx,roty,rotz
def rotate_points(points,angles=[0,0,0],mode='XYZ',origin=[0,0,0],offset=[0,0,0]): """ Definition to rotate points. Parameters ---------- points : ndarray Points. angles : list Rotation angles in degrees. mode : str Rotation mode determines ordering of the rotations at each axis. There are XYZ,YXZ,ZXY and ZYX modes. origin : list Reference point for a rotation. offset : list Shift with the given offset. Returns ---------- result : ndarray Result of the rotation """ points = np.asarray(points) if angles[0] == 0 and angles[1] == 0 and angles[2] ==0: result = np.array(offset) + points return result points -= np.array(origin) rotx = rotmatx(angles[0]) roty = rotmaty(angles[1]) rotz = rotmatz(angles[2]) if mode == 'XYZ': result = np.dot(rotz,np.dot(roty,np.dot(rotx,points.T))).T elif mode == 'XZY': result = np.dot(roty,np.dot(rotz,np.dot(rotx,points.T))).T elif mode == 'YXZ': result = np.dot(rotz,np.dot(rotx,np.dot(roty,points.T))).T elif mode == 'ZXY': result = np.dot(roty,np.dot(rotx,np.dot(rotz,points.T))).T elif mode == 'ZYX': result = np.dot(rotx,np.dot(roty,np.dot(rotz,points.T))).T result += np.array(origin) result += np.array(offset) return result