Skip to content

Test ray cylinder collision

3D: rays_cylinder_collision

python
import torchlensmaker as tlm
from torchlensmaker.sampling.samplers import uniform_disk_sampling

import torch

from torchlensmaker.testing.collision_datasets import NormalRays, FixedRays, OrbitalRays

from torchlensmaker.core.cylinder_collision import rays_cylinder_collision


def make_random_rays(num_rays, start_x, end_x, max_y, dtype):
    rays_start = (torch.rand((num_rays, 3), dtype=dtype) * 2 - 1) * max_y
    rays_start[:, 0] = start_x

    rays_end = (torch.rand((num_rays, 3)) * 2 - 1) * max_y
    rays_end[:, 0] = end_x

    rays_vectors = torch.nn.functional.normalize(rays_end - rays_start, dim=1)

    return torch.hstack((rays_start, rays_vectors))


def horizontal_rays(num_rays, start_x, diameter):
    points = uniform_disk_sampling(num_rays, diameter, torch.float64)

    P = torch.cat((torch.full((num_rays, 1), start_x), points), dim=-1)
    V = torch.tile(torch.tensor([1.0, 0., 0.], dtype=torch.float64), (num_rays, 1))

    return P, V

def zerox_rays(num_rays, start_x, diameter):
    "Rays with Vx == 0"

    P = (torch.rand((num_rays, 3)) - 0.5) * diameter
    P[:, 0] = start_x
    V = (torch.rand((num_rays, 3)) - 0.5) * diameter
    V[:, 0] = 0.
    V = torch.nn.functional.normalize(V, dim=-1)

    return P, V

def edge_rays(num_rays, start_x, tau):
    theta = torch.linspace(0., 2 * torch.pi, num_rays)
    x = tau * torch.cos(theta)
    y = tau * torch.sin(theta)
    P = torch.stack([torch.full((num_rays,), start_x), x, y], dim=1)
    V = torch.tile(torch.tensor([1.0, 0., 0.], dtype=torch.float64), (num_rays, 1))

    return P, V

def demo():
    test_rays = make_random_rays(
        num_rays=50,
        start_x=-5,
        end_x=5,
        max_y=12,
        dtype=torch.float64
    )

    P, V = test_rays[:, :3], test_rays[:, 3:6]

    # add some perfectly horizontal rays
    #P, V = horizontal_rays(100, -5, 12)
    #P, V = edge_rays(100, -5, 10 / 2)
    #P, V = zerox_rays(100, 0, 10)

    surface = tlm.Sphere(10, R=-6)

    # Compute ray cylinder intersection
    xmin, xmax, tau = surface.bcyl()
    t1, t2, hit_mask = rays_cylinder_collision(P, V, xmin, xmax, tau)

    point1 = P + t1.unsqueeze(-1).expand_as(V)*V
    point2 = P + t2.unsqueeze(-1).expand_as(V)*V

    valid_point1 = point1[hit_mask]
    valid_point2 = point2[hit_mask]

    # Setup scene for rendering
    scene = tlm.viewer.new_scene("3D")

    # Render surface
    tf = tlm.IdentityTransform(3, surface.dtype)
    scene["data"].append(tlm.viewer.render_surface(surface, tf.hom_matrix(), 3))

    # Render points
    scene["data"].append(tlm.viewer.render_points(valid_point1))
    scene["data"].append(tlm.viewer.render_points(valid_point2))
    
    # Render rays
    rays_length=30
    rays_start = P
    rays_end = P + rays_length*V
    scene["data"].append(
        tlm.viewer.render_rays(rays_start, rays_end, layer=0)
    )

    # Display
    scene["controls"] = {"show_bounding_cylinders": True}
    tlm.viewer.display_scene(scene)
    

demo()

2D: ray_box_collision

python
import torchlensmaker as tlm
import torch

from torchlensmaker.core.cylinder_collision import rays_rectangle_collision
from torchlensmaker.testing.collision_datasets import NormalRays, FixedRays, OrbitalRays


def make_random_rays(num_rays, start_x, end_x, max_y, dtype):
    rays_start = (torch.rand((num_rays, 2), dtype=dtype) * 2 - 1) * max_y
    rays_start[:, 0] = start_x

    rays_end = (torch.rand((num_rays, 2)) * 2 - 1) * max_y
    rays_end[:, 0] = end_x

    rays_vectors = torch.nn.functional.normalize(rays_end - rays_start, dim=1)

    return torch.hstack((rays_start, rays_vectors))


def horizontal_rays(num_rays, start_x, diameter):
    points = uniform_disk_sampling(num_rays, diameter, torch.float64)

    P = torch.cat((torch.full((num_rays, 1), start_x), points), dim=-1)
    V = torch.tile(torch.tensor([1.0, 0., 0.], dtype=torch.float64), (num_rays, 1))

    return P, V

def zerox_rays(num_rays, start_x, diameter):
    "Rays with Vx == 0"

    P = (torch.rand((num_rays, 3)) - 0.5) * diameter
    P[:, 0] = start_x
    V = (torch.rand((num_rays, 3)) - 0.5) * diameter
    V[:, 0] = 0.
    V = torch.nn.functional.normalize(V, dim=-1)

    return P, V

def edge_rays(num_rays, start_x, tau):
    theta = torch.linspace(0., 2 * torch.pi, num_rays)
    x = tau * torch.cos(theta)
    y = tau * torch.sin(theta)
    P = torch.stack([torch.full((num_rays,), start_x), x, y], dim=1)
    V = torch.tile(torch.tensor([1.0, 0., 0.], dtype=torch.float64), (num_rays, 1))

    return P, V

def demo():
    test_rays = make_random_rays(
        num_rays=50,
        start_x=-5,
        end_x=5,
        max_y=12,
        dtype=torch.float64
    )

    #P, V = test_rays[:, :2], test_rays[:, 2:4]

    # add some perfectly horizontal rays
    #P, V = horizontal_rays(100, -5, 12)
    #P, V = edge_rays(100, -5, 10 / 2)
    #P, V = zerox_rays(100, 0, 10)

    #surface = tlm.Sphere(10, R=-6)
    surface = tlm.SagSurface(10, tlm.SagSum([
        tlm.Conical(C=torch.tensor(0.01999999955296516), K=torch.tensor(1.)),
        tlm.Aspheric(coefficients=torch.tensor([-0.004999999888241291]))
    ]))

    generator = OrbitalRays(dim=2, N=15, radius=1.1, offset=0.0, epsilon=0.0)
    P, V = generator(surface)

    # Compute ray cylinder intersection
    xmin, xmax, tau = surface.bcyl()

    t1, t2, hit_mask = rays_rectangle_collision(P, V, xmin, xmax, -tau, tau)

    point1 = P + t1.unsqueeze(-1).expand_as(V)*V
    point2 = P + t2.unsqueeze(-1).expand_as(V)*V

    valid_point1 = point1[hit_mask]
    valid_point2 = point2[hit_mask]

    # Setup scene for rendering
    scene = tlm.viewer.new_scene("2D")

    # Render surface
    tf = tlm.IdentityTransform(2, surface.dtype).hom_matrix()
    scene["data"].append(tlm.viewer.render_surface(surface, tf, 2))

    # Render points
    scene["data"].append(tlm.viewer.render_points(valid_point1))
    scene["data"].append(tlm.viewer.render_points(valid_point2))
    
    # Render rays
    rays_length=30
    rays_start = P
    rays_end = P + rays_length*V
    scene["data"].append(
        tlm.viewer.render_rays(rays_start, rays_end, layer=0)
    )

    # Display
    scene["controls"] = {"show_bounding_cylinders": True}
    tlm.viewer.display_scene(scene)
    

demo()