Compute the intersection between grid cells and the ray. Args: ray_origins: (b, m, 3) ray_directions: (b, m, 3) ray_radius: (b,) grid_size: (b, 3) long, xyz grid_center: (b, 3), xyz grid_width: (b, 3), xyz Returns: list of list of list: b -> ray_idx -> grid_idx (including -1, outside the grid) Algorithm: for each ray (px, py, pz, dx, dy, dz) if dx.abs() < 1e-8: # use y=c plane else: # use x=c
| 311 | // surrounding the point. |
| 312 | // |
| 313 | std::vector<idxmap> grid_ray_intersection( |
| 314 | const torch::Tensor & ray_origins, // (b, m, 3), float |
| 315 | const torch::Tensor & ray_directions, // (b, m, 3), float |
| 316 | const torch::Tensor & ray_radius, // (b, )m float |
| 317 | const torch::Tensor & grid_size, // (b, 3), long |
| 318 | const torch::Tensor & grid_center, // (b, 3) float |
| 319 | const torch::Tensor & grid_width // (b, 3) float |
| 320 | ) { |
| 321 | |
| 322 | assert(grid_size.dtype() == torch::kLong); |
| 323 | |
| 324 | auto batch_size = ray_origins.size(0); |
| 325 | auto n_rays = ray_origins.size(1); |
| 326 | auto device = ray_origins.device(); |
| 327 | |
| 328 | auto grid_from = grid_center - grid_width * 0.5; // (b, 3) |
| 329 | auto cell_width = grid_width / grid_size; // (b, 3) |
| 330 | auto total_cells = torch::prod(grid_size, -1); // (b,) |
| 331 | |
| 332 | // determine whether to intersect with x=c plane, y=c plane, or z=c plane. |
| 333 | // It is important to select a direction so that the intersection point on two nearby planes |
| 334 | // do not exceed one grid in one of the rest of the two directions. |
| 335 | // Fortunately, it can be shown that it will always happen when we select wisely. |
| 336 | |
| 337 | // Let inv_tx = |dx / wx| (1 / time to travel one x grid) |
| 338 | // inv_ty = |dy / wy| (1 / time to travel one y grid) |
| 339 | // inv_tz = |dz / wz| (1 / time to travel one z grid) |
| 340 | // If inv_tx is the largest of (inv_tx, inv_ty, inv_tz) -> we will intersect with x=c planes. |
| 341 | // vise versa for inv_ty and inv_tz. |
| 342 | // When we select inv_tx, it ensures we move in the x direction in 1 grid, y and z in <= 1 grid. |
| 343 | |
| 344 | auto inv_t = (ray_directions / cell_width.unsqueeze(-2)).abs(); // (b, m, 3) |
| 345 | auto idx_to_use = torch::argmax(inv_t, -1); // (b, m) (0, 1, 2) |
| 346 | |
| 347 | // create accessors to each tensor |
| 348 | // auto start = high_resolution_clock::now(); |
| 349 | auto a_grid_from = grid_from.accessor<float, 2>(); // (b, 3) |
| 350 | auto a_cell_width = cell_width.accessor<float, 2>(); // (b, 3) |
| 351 | auto a_grid_size = grid_size.accessor<int64_t, 2>(); // (b, 3) |
| 352 | auto a_idx_to_use = idx_to_use.accessor<int64_t, 2>(); // (b, m) 0, 1, 2 |
| 353 | // auto stop = high_resolution_clock::now(); |
| 354 | // auto duration = duration_cast<microseconds>(stop - start); |
| 355 | // std::cout<<"accessor_time: "<<duration.count()<<std::endl; |
| 356 | |
| 357 | auto l_options = torch::TensorOptions().dtype(torch::kLong).device(device); |
| 358 | auto f_options = torch::TensorOptions().dtype(torch::kFloat32).device(device); |
| 359 | |
| 360 | |
| 361 | std::vector<idxmap> all_grid_idxs; |
| 362 | all_grid_idxs.reserve(batch_size); |
| 363 | for (auto b = 0; b < batch_size; ++b) { |
| 364 | |
| 365 | auto a_grid_size_b = a_grid_size[b]; |
| 366 | |
| 367 | // build a meshgrid for local grid idx. This will determine the neighboring grids to gather. |
| 368 | // the local grid width = 2 * local_grid_radius |
| 369 | auto local_grid_radius = (torch::ceil(ray_radius.index({b, None}) / cell_width[b] + 1)).to(torch::kLong); // (3,) long, xyz |
| 370 | auto grid_idx_from = -1 * local_grid_radius; // (3,) long, xyz |
no test coverage detected