Skip to content

Commit 9016cdb

Browse files
committed
python tests passing
1 parent 1ef1a33 commit 9016cdb

File tree

9 files changed

+2548
-3
lines changed

9 files changed

+2548
-3
lines changed

csrc/cpu/compat.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#ifdef VERSION_GE_1_3
2+
#define DATA_PTR data_ptr
3+
#else
4+
#define DATA_PTR data
5+
#endif

csrc/cpu/radius_cpu.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include "radius_cpu.h"
2+
3+
#include "utils.h"
4+
5+
torch::Tensor radius_cpu(torch::Tensor query, torch::Tensor support,
6+
torch::Tensor ptr_x, torch::Tensor ptr_y,
7+
float radius, int max_num){
8+
9+
CHECK_CPU(query);
10+
CHECK_CPU(support);
11+
12+
/*
13+
x = torch.cat([x, 2 * r * batch_x.view(-1, 1).to(x.dtype)], dim=-1)
14+
y = torch.cat([y, 2 * r * batch_y.view(-1, 1).to(y.dtype)], dim=-1)
15+
auto batch_x = ptr_x.clone();
16+
auto batch_y = ptr_y.clone();
17+
18+
batch_x._mul(2*radius);
19+
batch_y._mul(2*radius);
20+
21+
auto query = torch::cat({query,batch_x},-1);
22+
auto support = torch::cat({support,batch_y},-1);
23+
*/
24+
25+
torch::Tensor out;
26+
std::vector<long> neighbors_indices;
27+
auto options = torch::TensorOptions().dtype(torch::kLong).device(torch::kCPU);
28+
int max_count = 0;
29+
30+
AT_DISPATCH_ALL_TYPES(query.scalar_type(), "radius_cpu", [&] {
31+
32+
auto data_q = query.DATA_PTR<scalar_t>();
33+
auto data_s = support.DATA_PTR<scalar_t>();
34+
std::vector<scalar_t> queries_stl = std::vector<scalar_t>(data_q,
35+
data_q + query.size(0)*query.size(1));
36+
std::vector<scalar_t> supports_stl = std::vector<scalar_t>(data_s,
37+
data_s + support.size(0)*support.size(1));
38+
39+
int dim = torch::size(query, 1);
40+
41+
max_count = nanoflann_neighbors<scalar_t>(queries_stl, supports_stl ,neighbors_indices, radius, dim, max_num);
42+
43+
});
44+
45+
long* neighbors_indices_ptr = neighbors_indices.data();
46+
out = torch::from_blob(neighbors_indices_ptr, {neighbors_indices.size()/2, 2}, options=options);
47+
48+
return out.t().clone();
49+
}
50+
51+
void get_size_batch(const vector<long>& batch, vector<long>& res){
52+
53+
res.resize(batch[batch.size()-1]-batch[0]+1, 0);
54+
long ind = batch[0];
55+
long incr = 1;
56+
for(int i=1; i < batch.size(); i++){
57+
58+
if(batch[i] == ind)
59+
incr++;
60+
else{
61+
res[ind-batch[0]] = incr;
62+
incr =1;
63+
ind = batch[i];
64+
}
65+
}
66+
res[ind-batch[0]] = incr;
67+
}

csrc/cpu/radius_cpu.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include <torch/extension.h>
4+
#include <ATen/ATen.h>
5+
#include "utils/neighbors.h"
6+
#include "utils/neighbors.cpp"
7+
#include <iostream>
8+
#include "compat.h"
9+
10+
torch::Tensor radius_cpu(torch::Tensor query,
11+
torch::Tensor support,torch::Tensor ptr_x,
12+
torch::Tensor ptr_y,
13+
float radius, int max_num);
14+
/*
15+
using namespace pybind11::literals;
16+
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
17+
m.def("radius_search",
18+
&radius_search,
19+
"compute the radius search of a point cloud using nanoflann"
20+
"-query : a pytorch tensor of size N1 x d,. used to query the nearest neighbors"
21+
"- support : a pytorch tensor of size N2 x d. used to build the tree"
22+
"- radius : float number, size of the ball for the radius search."
23+
"- max_num : int number, indicate the maximum of neaghbors allowed(if -1 then all the possible neighbors will be computed). "
24+
" - mode : int number that indicate which format for the neighborhood"
25+
" mode=0 mean a matrix of neighbors(-1 for shadow neighbors)"
26+
"mode=1 means a matrix of edges of size Num_edge x 2"
27+
"return a tensor of size N1 x M where M is either max_num or the maximum number of neighbors found if mode = 0, if mode=1 return a tensor of size Num_edge x 2.",
28+
"query"_a, "support"_a, "radius"_a, "dim"_a, "max_num"_a=-1, "mode"_a=0);
29+
m.def("batch_radius_search",
30+
&batch_radius_search,
31+
"compute the radius search of a point cloud for each batch using nanoflann"
32+
"-query : a pytorch tensor (float) of size N1 x d,. used to query the nearest neighbors"
33+
"- support : a pytorch tensor(float) of size N2 x d. used to build the tree"
34+
"- query_batch : a pytorch tensor(long) contains indices of the batch of the query size N1"
35+
"NB : the batch must be sorted"
36+
"- support_batch: a pytorch tensor(long) contains indices of the batch of the support size N2"
37+
"NB: the batch must be sorted"
38+
"-radius: float number, size of the ball for the radius search."
39+
"- max_num : int number, indicate the maximum of neaghbors allowed(if -1 then all the possible neighbors wrt the radius will be computed)."
40+
"- mode : int number that indicate which format for the neighborhood"
41+
"mode=0 mean a matrix of neighbors(N2 for shadow neighbors)"
42+
"mode=1 means a matrix of edges of size Num_edge x 2"
43+
"return a tensor of size N1 x M where M is either max_num or the maximum number of neighbors found if mode = 0, if mode=1 return a tensor of size Num_edge x 2.",
44+
"query"_a, "support"_a, "query_batch"_a, "support_batch"_a, "radius"_a, "dim"_a, "max_num"_a=-1, "mode"_a=0);
45+
}
46+
*/

csrc/cpu/utils/cloud.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Author: Peiyuan Liao (alexander_liao@outlook.com)
2+
//
3+
4+
5+
# pragma once
6+
7+
#include <ATen/ATen.h>
8+
#include <cmath>
9+
#include <vector>
10+
#include <unordered_map>
11+
#include <map>
12+
#include <algorithm>
13+
#include <numeric>
14+
#include <iostream>
15+
#include <iomanip>
16+
17+
#include <time.h>
18+
19+
20+
template<typename scalar_t>
21+
struct PointCloud
22+
{
23+
std::vector<std::vector<scalar_t>> pts;
24+
25+
void set(std::vector<scalar_t> new_pts, int dim){
26+
27+
// pts = std::vector<Point>((Point*)new_pts, (Point*)new_pts+new_pts.size()/3);
28+
std::vector<std::vector<scalar_t>> temp(new_pts.size()/dim);
29+
for(unsigned int i=0; i < new_pts.size(); i++){
30+
if(i%dim == 0){
31+
32+
//Point point;
33+
std::vector<scalar_t> point(dim);
34+
//std::vector<scalar_t> vect(sizeof(scalar_t)*dim, 0)
35+
//point.pt = temp;
36+
for (unsigned int j = 0; j < dim; j++) {
37+
point[j]=new_pts[i+j];
38+
//point.pt[j] = new_pts[i+j];
39+
}
40+
temp[i/dim] = point;
41+
}
42+
}
43+
44+
pts = temp;
45+
}
46+
void set_batch(std::vector<scalar_t> new_pts, int begin, int size, int dim){
47+
std::vector<std::vector<scalar_t>> temp(size);
48+
for(int i=0; i < size; i++){
49+
//std::vector<scalar_t> temp(sizeof(scalar_t)*dim, 0);
50+
//point.pt = temp;
51+
std::vector<scalar_t> point(dim);
52+
for (unsigned int j = 0; j < dim; j++) {
53+
point[j] = new_pts[dim*(begin+i)+j];
54+
}
55+
56+
temp[i] = point;
57+
58+
}
59+
pts = temp;
60+
}
61+
62+
// Must return the number of data points
63+
inline size_t kdtree_get_point_count() const { return pts.size(); }
64+
65+
// Returns the dim'th component of the idx'th point in the class:
66+
inline scalar_t kdtree_get_pt(const size_t idx, const size_t dim) const
67+
{
68+
return pts[idx][dim];
69+
}
70+
71+
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
72+
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
73+
// Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
74+
template <class BBOX>
75+
bool kdtree_get_bbox(BBOX& /* bb */) const { return false; }
76+
77+
78+
};

0 commit comments

Comments
 (0)