# odak.learn.raytracing

## odak.learn.raytracing¶

Provides necessary definitions for geometric optics. See "General Ray tracing procedure" from G.H. Spencerand M.V.R.K Murty for more theoratical explanation.

## get_sphere_normal_torch(point, sphere)¶

Definition to get a normal of a point on a given sphere.

Parameters:

• point
        Point on sphere in X,Y,Z.

• sphere
        Center defined in X,Y,Z and radius.


Returns:

• normal_vector ( tensor ) –

Normal vector.

Source code in odak/learn/raytracing/boundary.py
 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 def get_sphere_normal_torch(point, sphere): """ Definition to get a normal of a point on a given sphere. Parameters ---------- point : torch.tensor Point on sphere in X,Y,Z. sphere : torch.tensor Center defined in X,Y,Z and radius. Returns ---------- normal_vector : torch.tensor Normal vector. """ if len(point.shape) == 1: point = point.reshape((1, 3)) normal_vector = create_ray_from_two_points(point, sphere[0:3]) return normal_vector 

## get_triangle_normal(triangle, triangle_center=None)¶

Definition to calculate surface normal of a triangle.

Parameters:

• triangle
          Set of points in X,Y and Z to define a planar surface (3,3). It can also be list of triangles (mx3x3).

• triangle_center (tensor, default: None ) –
          Center point of the given triangle. See odak.learn.raytracing.center_of_triangle for more. In many scenarios you can accelerate things by precomputing triangle centers.


Returns:

• normal ( tensor ) –

Surface normal at the point of intersection.

Source code in odak/learn/raytracing/boundary.py
 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 def get_triangle_normal(triangle, triangle_center=None): """ Definition to calculate surface normal of a triangle. Parameters ---------- triangle : torch.tensor Set of points in X,Y and Z to define a planar surface (3,3). It can also be list of triangles (mx3x3). triangle_center : torch.tensor Center point of the given triangle. See odak.learn.raytracing.center_of_triangle for more. In many scenarios you can accelerate things by precomputing triangle centers. Returns ---------- normal : torch.tensor Surface normal at the point of intersection. """ if len(triangle.shape) == 2: triangle = triangle.view((1, 3, 3)) normal = torch.zeros((triangle.shape, 2, 3)).to(triangle.device) direction = torch.cross( triangle[:, 0] - triangle[:, 1], triangle[:, 2] - triangle[:, 1] ) if type(triangle_center) == type(None): normal[:, 0] = center_of_triangle(triangle) else: normal[:, 0] = triangle_center normal[:, 1] = direction / torch.sum(direction, axis=1) if normal.shape == 1: normal = normal.view((2, 3)) return normal 

## intersect_w_circle(ray, circle)¶

Definition to find intersection point of a ray with a circle. Returns distance as zero if there isn't an intersection.

Parameters:

• ray
       A vector/ray.

• circle
       A list that contains (0) Set of points in X,Y and Z to define plane of a circle, (1) circle center, and (2) circle radius.


Returns:

• normal ( Tensor ) –

Surface normal at the point of intersection.

• distance ( Tensor ) –

Distance in between a starting point of a ray and the intersection point with a given triangle.

Source code in odak/learn/raytracing/boundary.py
 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 def intersect_w_circle(ray, circle): """ Definition to find intersection point of a ray with a circle. Returns distance as zero if there isn't an intersection. Parameters ---------- ray : torch.Tensor A vector/ray. circle : list A list that contains (0) Set of points in X,Y and Z to define plane of a circle, (1) circle center, and (2) circle radius. Returns ---------- normal : torch.Tensor Surface normal at the point of intersection. distance : torch.Tensor Distance in between a starting point of a ray and the intersection point with a given triangle. """ normal, distance = intersect_w_surface(ray, circle) if len(normal.shape) == 2: normal = normal.unsqueeze(0) distance_to_center = distance_between_two_points(normal[:, 0], circle) mask = distance_to_center > circle distance[mask] = 0 if len(ray.shape) == 2: normal = normal.squeeze(0) return normal, distance 

## intersect_w_sphere(ray, sphere, learning_rate=0.2, number_of_steps=5000, error_threshold=0.01)¶

Definition to find the intersection between ray(s) and sphere(s).

Parameters:

• ray
              Input ray(s).
Expected size is [1 x 2 x 3] or [m x 2 x 3].

• sphere
              Input sphere.
Expected size is [1 x 4].

• learning_rate
              Learning rate used in the optimizer for finding the propagation distances of the rays.

• number_of_steps
              Number of steps used in the optimizer.

• error_threshold
              The error threshold that will help deciding intersection or no intersection.


Returns:

• intersecting_ray ( tensor ) –

Ray(s) that intersecting with the given sphere. Expected size is [n x 2 x 3], where n could be any real number.

• intersecting_normal ( tensor ) –

Normal(s) for the ray(s) intersecting with the given sphere Expected size is [n x 2 x 3], where n could be any real number.

Source code in odak/learn/raytracing/boundary.py
  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 def intersect_w_sphere(ray, sphere, learning_rate = 2e-1, number_of_steps = 5000, error_threshold = 1e-2): """ Definition to find the intersection between ray(s) and sphere(s). Parameters ---------- ray : torch.tensor Input ray(s). Expected size is [1 x 2 x 3] or [m x 2 x 3]. sphere : torch.tensor Input sphere. Expected size is [1 x 4]. learning_rate : float Learning rate used in the optimizer for finding the propagation distances of the rays. number_of_steps : int Number of steps used in the optimizer. error_threshold : float The error threshold that will help deciding intersection or no intersection. Returns ------- intersecting_ray : torch.tensor Ray(s) that intersecting with the given sphere. Expected size is [n x 2 x 3], where n could be any real number. intersecting_normal : torch.tensor Normal(s) for the ray(s) intersecting with the given sphere Expected size is [n x 2 x 3], where n could be any real number. """ if len(ray.shape) == 2: ray = ray.unsqueeze(0) if len(sphere.shape) == 1: sphere = sphere.unsqueeze(0) distance = torch.zeros(ray.shape, device = ray.device, requires_grad = True) loss_l2 = torch.nn.MSELoss(reduction = 'sum') optimizer = torch.optim.AdamW([distance], lr = learning_rate) t = tqdm(range(number_of_steps), leave = False, dynamic_ncols = True) for step in t: optimizer.zero_grad() propagated_ray = propagate_ray(ray, distance) test = torch.abs((propagated_ray[:, 0, 0] - sphere[:, 0]) ** 2 + (propagated_ray[:, 0, 1] - sphere[:, 1]) ** 2 + (propagated_ray[:, 0, 2] - sphere[:, 2]) ** 2 - sphere[:, 3] ** 2) loss = loss_l2( test, torch.zeros_like(test) ) loss.backward(retain_graph = True) optimizer.step() t.set_description('Sphere intersection loss: {}'.format(loss.item())) check = test < error_threshold intersecting_ray = propagate_ray(ray[check == True], distance[check == True]) intersecting_normal = create_ray_from_two_points( sphere[:, 0:3], intersecting_ray[:, 0] ) return intersecting_ray, intersecting_normal, distance, check 

## 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
       A vector/ray.

• points
       Set of points in X,Y and Z to define a planar surface.


Returns:

• normal ( tensor ) –

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.

Source code in odak/learn/raytracing/boundary.py
 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 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 : torch.tensor A vector/ray. points : torch.tensor Set of points in X,Y and Z to define a planar surface. Returns ---------- normal : torch.tensor 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. """ normal = get_triangle_normal(points) if len(ray.shape) == 2: ray = ray.unsqueeze(0) if len(points) == 2: points = points.unsqueeze(0) if len(normal.shape) == 2: normal = normal.unsqueeze(0) f = normal[:, 0] - ray[:, 0] distance = (torch.mm(normal[:, 1], f.T) / torch.mm(normal[:, 1], ray[:, 1].T)).T new_normal = torch.zeros_like(ray) new_normal[:, 0] = ray[:, 0] + distance * ray[:, 1] new_normal[:, 1] = normal[:, 1] new_normal = torch.nan_to_num( new_normal, nan = float('nan'), posinf = float('nan'), neginf = float('nan') ) distance = torch.nan_to_num( distance, nan = float('nan'), posinf = float('nan'), neginf = float('nan') ) return new_normal, distance 

## intersect_w_triangle(ray, triangle)¶

Definition to find intersection point of a ray with a triangle.

Parameters:

• ray
              A ray [1 x 2 x 3] or a batch of ray [m x 2 x 3].

• triangle
              Set of points in X,Y and Z to define a single triangle [1 x 3 x 3].


Returns:

• normal ( tensor ) –

Surface normal at the point of intersection with the surface of triangle. This could also involve surface normals that are not on the triangle. Expected size is [1 x 2 x 3] or [m x 2 x 3] depending on the input.

• distance ( float ) –

Distance in between a starting point of a ray and the intersection point with a given triangle. Expected size is [1 x 1] or [m x 1] depending on the input.

• intersecting_ray ( tensor ) –

Rays that intersect with the triangle plane and on the triangle. Expected size is [1 x 2 x 3] or [m x 2 x 3] depending on the input.

• intersecting_normal ( tensor ) –

Normals that intersect with the triangle plane and on the triangle. Expected size is [1 x 2 x 3] or [m x 2 x 3] depending on the input.

• check ( tensor ) –

A list that provides a bool as True or False for each ray used as input. A test to see is a ray could be on the given triangle. Expected size is  or [m].

Source code in odak/learn/raytracing/boundary.py
 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 def intersect_w_triangle(ray, triangle): """ Definition to find intersection point of a ray with a triangle. Parameters ---------- ray : torch.tensor A ray [1 x 2 x 3] or a batch of ray [m x 2 x 3]. triangle : torch.tensor Set of points in X,Y and Z to define a single triangle [1 x 3 x 3]. Returns ---------- normal : torch.tensor Surface normal at the point of intersection with the surface of triangle. This could also involve surface normals that are not on the triangle. Expected size is [1 x 2 x 3] or [m x 2 x 3] depending on the input. distance : float Distance in between a starting point of a ray and the intersection point with a given triangle. Expected size is [1 x 1] or [m x 1] depending on the input. intersecting_ray : torch.tensor Rays that intersect with the triangle plane and on the triangle. Expected size is [1 x 2 x 3] or [m x 2 x 3] depending on the input. intersecting_normal : torch.tensor Normals that intersect with the triangle plane and on the triangle. Expected size is [1 x 2 x 3] or [m x 2 x 3] depending on the input. check : torch.tensor A list that provides a bool as True or False for each ray used as input. A test to see is a ray could be on the given triangle. Expected size is  or [m]. """ if len(triangle.shape) == 2: triangle = triangle.unsqueeze(0) if len(ray.shape) == 2: ray = ray.unsqueeze(0) normal, distance = intersect_w_surface(ray, triangle) check = is_it_on_triangle(normal[:, 0], triangle) intersecting_ray = ray.unsqueeze(0) intersecting_ray = intersecting_ray.repeat(triangle.shape, 1, 1, 1) intersecting_ray = intersecting_ray[check == True] intersecting_normal = normal.unsqueeze(0) intersecting_normal = intersecting_normal.repeat(triangle.shape, 1, 1, 1) intersecting_normal = intersecting_normal[check == True] return normal, distance, intersecting_ray, intersecting_normal, check 

## reflect(input_ray, normal)¶

Definition to reflect an incoming ray from a surface defined by a surface normal. Used method described in G.H. Spencer and M.V.R.K. Murty, "General Ray-Tracing Procedure", 1961.

Parameters:

• input_ray
       A ray or rays.
Expected size is [2 x 3], [1 x 2 x 3] or [m x 2 x 3].

• normal
       A surface normal(s).
Expected size is [2 x 3], [1 x 2 x 3] or [m x 2 x 3].


Returns:

• output_ray ( tensor ) –

Array that contains starting points and cosines of a reflected ray. Expected size is [1 x 2 x 3] or [m x 2 x 3].

Source code in odak/learn/raytracing/boundary.py
 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 def reflect(input_ray, normal): """ Definition to reflect an incoming ray from a surface defined by a surface normal. Used method described in G.H. Spencer and M.V.R.K. Murty, "General Ray-Tracing Procedure", 1961. Parameters ---------- input_ray : torch.tensor A ray or rays. Expected size is [2 x 3], [1 x 2 x 3] or [m x 2 x 3]. normal : torch.tensor A surface normal(s). Expected size is [2 x 3], [1 x 2 x 3] or [m x 2 x 3]. Returns ---------- output_ray : torch.tensor Array that contains starting points and cosines of a reflected ray. Expected size is [1 x 2 x 3] or [m x 2 x 3]. """ if len(input_ray.shape) == 2: input_ray = input_ray.unsqueeze(0) if len(normal.shape) == 2: normal = normal.unsqueeze(0) mu = 1 div = normal[:, 1, 0]**2 + normal[:, 1, 1]**2 + normal[:, 1, 2]**2 + 1e-8 a = mu * (input_ray[:, 1, 0] * normal[:, 1, 0] + input_ray[:, 1, 1] * normal[:, 1, 1] + input_ray[:, 1, 2] * normal[:, 1, 2]) / div a = a.unsqueeze(1) n = int(torch.amax(torch.tensor([normal.shape, input_ray.shape]))) output_ray = torch.zeros((n, 2, 3)).to(input_ray.device) output_ray[:, 0] = normal[:, 0] output_ray[:, 1] = input_ray[:, 1] - 2 * a * normal[:, 1] return output_ray 

## refract(vector, normvector, n1, n2, error=0.01)¶

Definition to refract an incoming ray. Used method described in G.H. Spencer and M.V.R.K. Murty, "General Ray-Tracing Procedure", 1961.

Parameters:

• vector
         Incoming ray.
Expected size is [2, 3], [1, 2, 3] or [m, 2, 3].

• normvector
         Normal vector.
Expected size is [2, 3], [1, 2, 3] or [m, 2, 3]].

• n1
         Refractive index of the incoming medium.

• n2
         Refractive index of the outgoing medium.

• error
         Desired error.


Returns:

• output ( tensor ) –

Refracted ray. Expected size is [1, 2, 3]

Source code in odak/learn/raytracing/boundary.py
  8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 def refract(vector, normvector, n1, n2, error = 0.01): """ Definition to refract an incoming ray. Used method described in G.H. Spencer and M.V.R.K. Murty, "General Ray-Tracing Procedure", 1961. Parameters ---------- vector : torch.tensor Incoming ray. Expected size is [2, 3], [1, 2, 3] or [m, 2, 3]. normvector : torch.tensor Normal vector. Expected size is [2, 3], [1, 2, 3] or [m, 2, 3]]. n1 : float Refractive index of the incoming medium. n2 : float Refractive index of the outgoing medium. error : float Desired error. Returns ------- output : torch.tensor Refracted ray. Expected size is [1, 2, 3] """ if len(vector.shape) == 2: vector = vector.unsqueeze(0) if len(normvector.shape) == 2: normvector = normvector.unsqueeze(0) mu = n1 / n2 div = normvector[:, 1, 0] ** 2 + normvector[:, 1, 1] ** 2 + normvector[:, 1, 2] ** 2 a = mu * (vector[:, 1, 0] * normvector[:, 1, 0] + vector[:, 1, 1] * normvector[:, 1, 1] + vector[:, 1, 2] * normvector[:, 1, 2]) / div b = (mu ** 2 - 1) / div to = - b * 0.5 / a num = 0 eps = torch.ones(vector.shape, device = vector.device) * error * 2 while len(eps[eps > error]) > 0: num += 1 oldto = to v = to ** 2 + 2 * a * to + b deltav = 2 * (to + a) to = to - v / deltav eps = abs(oldto - to) output = torch.zeros_like(vector) output[:, 0, 0] = normvector[:, 0, 0] output[:, 0, 1] = normvector[:, 0, 1] output[:, 0, 2] = normvector[:, 0, 2] output[:, 1, 0] = mu * vector[:, 1, 0] + to * normvector[:, 1, 0] output[:, 1, 1] = mu * vector[:, 1, 1] + to * normvector[:, 1, 1] output[:, 1, 2] = mu * vector[:, 1, 2] + to * normvector[:, 1, 2] return output 

## center_of_triangle(triangle)¶

Definition to calculate center of a triangle.

Parameters:

• triangle
        An array that contains three points defining a triangle (Mx3).
It can also parallel process many triangles (NxMx3).


Returns:

• centers ( tensor ) –

Triangle centers.

Source code in odak/learn/raytracing/primitives.py
  82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 def center_of_triangle(triangle): """ Definition to calculate center of a triangle. Parameters ---------- triangle : torch.tensor An array that contains three points defining a triangle (Mx3). It can also parallel process many triangles (NxMx3). Returns ------- centers : torch.tensor Triangle centers. """ if len(triangle.shape) == 2: triangle = triangle.view((1, 3, 3)) center = torch.mean(triangle, axis=1) return center 

## define_circle(center, radius, angles)¶

Definition to describe a circle in a single variable packed form.

Parameters:

• center
  Center of a circle to be defined in 3D space.

• radius
  Radius of a circle to be defined.

• angles
  Angular tilt of a circle represented by rotations about x, y, and z axes.


Returns:

• circle ( list ) –

Single variable packed form.

Source code in odak/learn/raytracing/primitives.py
 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 def define_circle(center, radius, angles): """ Definition to describe a circle in a single variable packed form. Parameters ---------- center : torch.Tensor Center of a circle to be defined in 3D space. radius : float Radius of a circle to be defined. angles : torch.Tensor Angular tilt of a circle represented by rotations about x, y, and z axes. Returns ---------- circle : list Single variable packed form. """ points = define_plane(center, angles=angles) circle = [ points, center, torch.tensor([radius]) ] return circle 

## define_plane(point, angles=torch.tensor([0.0, 0.0, 0.0]))¶

Definition to generate a rotation matrix along X axis.

Parameters:

• point
       A point that is at the center of a plane.

• angles
       Rotation angles in degrees.


Returns:

• plane ( tensor ) –

Points defining plane.

Source code in odak/learn/raytracing/primitives.py
  6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 def define_plane(point, angles = torch.tensor([0., 0., 0.])): """ Definition to generate a rotation matrix along X axis. Parameters ---------- point : torch.tensor A point that is at the center of a plane. angles : torch.tensor Rotation angles in degrees. Returns ---------- plane : torch.tensor Points defining plane. """ plane = torch.tensor([ [10., 10., 0.], [0., 10., 0.], [0., 0., 0.] ], device = point.device) for i in range(0, plane.shape): plane[i], _, _, _ = rotate_points(plane[i], angles = angles.to(point.device)) plane[i] = plane[i] + point return plane 

## define_plane_mesh(number_of_meshes=[10, 10], size=[1.0, 1.0], angles=torch.tensor([0.0, 0.0, 0.0]), offset=torch.tensor([[0.0, 0.0, 0.0]]))¶

Definition to generate a plane with meshes.

Parameters:

• number_of_meshes
            Number of squares over plane.
There are two triangles at each square.

• size
            Size of the plane.

• angles
            Rotation angles in degrees.

• offset
            Offset along XYZ axes.
Expected dimension is [1 x 3] or offset for each triangle [m x 3].
m here refers to 2 * number_of_meshes times  number_of_meshes.


Returns:

• triangles ( tensor ) –

Triangles [m x 3 x 3], where m is 2 * number_of_meshes times number_of_meshes.

Source code in odak/learn/raytracing/primitives.py
 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 def define_plane_mesh( number_of_meshes = [10, 10], size = [1., 1.], angles = torch.tensor([0., 0., 0.]), offset = torch.tensor([[0., 0., 0.]]) ): """ Definition to generate a plane with meshes. Parameters ----------- number_of_meshes : torch.tensor Number of squares over plane. There are two triangles at each square. size : list Size of the plane. angles : torch.tensor Rotation angles in degrees. offset : torch.tensor Offset along XYZ axes. Expected dimension is [1 x 3] or offset for each triangle [m x 3]. m here refers to 2 * number_of_meshes times number_of_meshes. Returns ------- triangles : torch.tensor Triangles [m x 3 x 3], where m is 2 * number_of_meshes times number_of_meshes. """ triangles = torch.zeros(2, number_of_meshes, number_of_meshes, 3, 3) step = [size / number_of_meshes, size / number_of_meshes] for i in range(0, number_of_meshes - 1): for j in range(0, number_of_meshes - 1): first_triangle = torch.tensor([ [ -size / 2. + step * i, -size / 2. + step * j, 0.], [ -size / 2. + step * (i + 1), -size / 2. + step * j, 0.], [ -size / 2. + step * i, -size / 2. + step * (j + 1), 0.] ]) second_triangle = torch.tensor([ [ -size / 2. + step * (i + 1), -size / 2. + step * (j + 1), 0.], [ -size / 2. + step * (i + 1), -size / 2. + step * j, 0.], [ -size / 2. + step * i, -size / 2. + step * (j + 1), 0.] ]) triangles[0, i, j], _, _, _ = rotate_points(first_triangle, angles = angles) triangles[1, i, j], _, _, _ = rotate_points(second_triangle, angles = angles) triangles = triangles.view(-1, 3, 3) + offset return triangles 

## define_sphere(center=torch.tensor([[0.0, 0.0, 0.0]]), radius=torch.tensor([1.0]))¶

Definition to define a sphere.

Parameters:

• center
      Center of the sphere(s) along XYZ axes.
Expected size is , [1, 3] or [m, 3].

• radius
      Radius of that sphere(s).
Expected size is , [1, 1], [m] or [m, 1].


Returns:

• parameters ( tensor ) –

Parameters of defined sphere(s). Expected size is [1, 3] or [m x 3].

Source code in odak/learn/raytracing/primitives.py
 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 def define_sphere(center = torch.tensor([[0., 0., 0.]]), radius = torch.tensor([1.])): """ Definition to define a sphere. Parameters ---------- center : torch.tensor Center of the sphere(s) along XYZ axes. Expected size is , [1, 3] or [m, 3]. radius : torch.tensor Radius of that sphere(s). Expected size is , [1, 1], [m] or [m, 1]. Returns ------- parameters : torch.tensor Parameters of defined sphere(s). Expected size is [1, 3] or [m x 3]. """ if len(radius.shape) == 1: radius = radius.unsqueeze(0) if len(center.shape) == 1: center = center.unsqueeze(1) parameters = torch.cat((center, radius), dim = 1) return parameters 

## is_it_on_triangle(point_to_check, triangle)¶

Definition to check if a given point is inside a triangle. If the given point is inside a defined triangle, this definition returns True. For more details, visit: https://blackpawn.com/texts/pointinpoly/.

Parameters:

• point_to_check
          Point(s) to check.
Expected size is , [1 x 3] or [m x 3].

• triangle
          Triangle described with three points.
Expected size is [3 x 3], [1 x 3 x 3] or [m x 3 x3].


Returns:

• result ( tensor ) –

Is it on a triangle? Returns NaN if condition not satisfied. Expected size is  or [m] depending on the input.

Source code in odak/learn/raytracing/primitives.py
 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 def is_it_on_triangle(point_to_check, triangle): """ Definition to check if a given point is inside a triangle. If the given point is inside a defined triangle, this definition returns True. For more details, visit: [https://blackpawn.com/texts/pointinpoly/](https://blackpawn.com/texts/pointinpoly/). Parameters ---------- point_to_check : torch.tensor Point(s) to check. Expected size is , [1 x 3] or [m x 3]. triangle : torch.tensor Triangle described with three points. Expected size is [3 x 3], [1 x 3 x 3] or [m x 3 x3]. Returns ------- result : torch.tensor Is it on a triangle? Returns NaN if condition not satisfied. Expected size is  or [m] depending on the input. """ if len(point_to_check.shape) == 1: point_to_check = point_to_check.unsqueeze(0) if len(triangle.shape) == 2: triangle = triangle.unsqueeze(0) v0 = triangle[:, 2] - triangle[:, 0] v1 = triangle[:, 1] - triangle[:, 0] v2 = point_to_check - triangle[:, 0] if len(v0.shape) == 1: v0 = v0.unsqueeze(0) if len(v1.shape) == 1: v1 = v1.unsqueeze(0) if len(v2.shape) == 1: v2 = v2.unsqueeze(0) dot00 = torch.mm(v0, v0.T) dot01 = torch.mm(v0, v1.T) dot02 = torch.mm(v0, v2.T) dot11 = torch.mm(v1, v1.T) dot12 = torch.mm(v1, v2.T) invDenom = 1. / (dot00 * dot11 - dot01 * dot01) u = (dot11 * dot02 - dot01 * dot12) * invDenom v = (dot00 * dot12 - dot01 * dot02) * invDenom result = (u >= 0.) & (v >= 0.) & ((u + v) < 1) return result 

## create_ray(xyz, abg)¶

Definition to create a ray.

Parameters:

• xyz
       List that contains X,Y and Z start locations of a ray.
Size could be [1 x 3], , [m x 3].

• abg
       List that contains angles in degrees with respect to the X,Y and Z axes.
Size could be [1 x 3], , [m x 3].


Returns:

• ray ( tensor ) –

Array that contains starting points and cosines of a created ray. Size will be either [1 x 3] or [m x 3].

Source code in odak/learn/raytracing/ray.py
  6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def create_ray(xyz, abg): """ Definition to create a ray. Parameters ---------- xyz : torch.tensor List that contains X,Y and Z start locations of a ray. Size could be [1 x 3], , [m x 3]. abg : torch.tensor List that contains angles in degrees with respect to the X,Y and Z axes. Size could be [1 x 3], , [m x 3]. Returns ---------- ray : torch.tensor Array that contains starting points and cosines of a created ray. Size will be either [1 x 3] or [m x 3]. """ points = xyz angles = abg if len(xyz) == 1: points = xyz.unsqueeze(0) if len(abg) == 1: angles = abg.unsqueeze(0) ray = torch.zeros(points.shape, 2, 3, device = points.device) ray[:, 0] = points ray[:, 1] = torch.cos(torch.deg2rad(abg)) return ray 

## create_ray_from_two_points(x0y0z0, x1y1z1)¶

Definition to create a ray from two given points. Note that both inputs must match in shape.

Parameters:

• x0y0z0
       List that contains X,Y and Z start locations of a ray.
Size could be [1 x 3], , [m x 3].

• x1y1z1
       List that contains X,Y and Z ending locations of a ray or batch of rays.
Size could be [1 x 3], , [m x 3].


Returns:

• ray ( tensor ) –

Array that contains starting points and cosines of a created ray(s).

Source code in odak/learn/raytracing/ray.py
 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 def create_ray_from_two_points(x0y0z0, x1y1z1): """ Definition to create a ray from two given points. Note that both inputs must match in shape. Parameters ---------- x0y0z0 : torch.tensor List that contains X,Y and Z start locations of a ray. Size could be [1 x 3], , [m x 3]. x1y1z1 : torch.tensor List that contains X,Y and Z ending locations of a ray or batch of rays. Size could be [1 x 3], , [m x 3]. Returns ---------- ray : torch.tensor Array that contains starting points and cosines of a created ray(s). """ if len(x0y0z0.shape) == 1: x0y0z0 = x0y0z0.unsqueeze(0) if len(x1y1z1.shape) == 1: x1y1z1 = x1y1z1.unsqueeze(0) xdiff = x1y1z1[:, 0] - x0y0z0[:, 0] ydiff = x1y1z1[:, 1] - x0y0z0[:, 1] zdiff = x1y1z1[:, 2] - x0y0z0[:, 2] s = (xdiff ** 2 + ydiff ** 2 + zdiff ** 2) ** 0.5 s[s == 0] = float('nan') cosines = torch.zeros_like(x0y0z0 * x1y1z1) cosines[:, 0] = xdiff / s cosines[:, 1] = ydiff / s cosines[:, 2] = zdiff / s ray = torch.zeros(xdiff.shape, 2, 3, device = x0y0z0.device) ray[:, 0] = x0y0z0 ray[:, 1] = cosines return ray 

## propagate_ray(ray, distance)¶

Definition to propagate a ray at a certain given distance.

Parameters:

• ray
     A ray with a size of [2 x 3], [1 x 2 x 3] or a batch of rays with [m x 2 x 3].

• distance
     Distance with a size of , [1, m] or distances with a size of [m], [1, m].


Returns:

• new_ray ( tensor ) –

Propagated ray with a size of [1 x 2 x 3] or batch of rays with [m x 2 x 3].

Source code in odak/learn/raytracing/ray.py
 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 def propagate_ray(ray, distance): """ Definition to propagate a ray at a certain given distance. Parameters ---------- ray : torch.tensor A ray with a size of [2 x 3], [1 x 2 x 3] or a batch of rays with [m x 2 x 3]. distance : torch.tensor Distance with a size of , [1, m] or distances with a size of [m], [1, m]. Returns ---------- new_ray : torch.tensor Propagated ray with a size of [1 x 2 x 3] or batch of rays with [m x 2 x 3]. """ if len(ray.shape) == 2: ray = ray.unsqueeze(0) if len(distance.shape) == 2: distance = distance.squeeze(-1) new_ray = torch.zeros_like(ray) new_ray[:, 0, 0] = distance * ray[:, 1, 0] + ray[:, 0, 0] new_ray[:, 0, 1] = distance * ray[:, 1, 1] + ray[:, 0, 1] new_ray[:, 0, 2] = distance * ray[:, 1, 2] + ray[:, 0, 2] return new_ray