12 #include <Eigen/Eigenvalues>
21 namespace pcapartition {
24 typedef std::vector<size_t> IdxVec;
33 template <
class TReal>
34 void Split(
const TReal*
const points,
35 const size_t num_points,
36 const IdxVec& indices,
37 std::vector<IdxVec>& output) {
42 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver;
43 solver.computeDirect(cov, Eigen::ComputeEigenvectors);
44 Eigen::Matrix<TReal, 3, 1> ax = solver.eigenvectors().col(2).cast<TReal>();
46 Eigen::Matrix<TReal, 3, 1> mu = mean.cast<TReal>();
47 Eigen::Map<const Eigen::Matrix<TReal, 3, Eigen::Dynamic>> pts(
points, 3,
49 TReal mindot = ax.dot(pts.col(indices.front()) - mu);
50 TReal maxdot = mindot;
51 for (
auto idx : indices) {
52 TReal
dot = ax.dot(pts.col(idx) - mu);
56 TReal center = TReal(0.5) * (mindot + maxdot);
58 for (
auto idx : indices) {
59 TReal
dot = ax.dot(pts.col(idx) - mu);
67 if (part1.empty() || part2.empty()) {
72 part1.insert(part1.begin(), indices.begin(),
73 indices.begin() + indices.size() / 2);
74 part2.insert(part2.begin(), indices.begin() + indices.size() / 2,
78 output.emplace_back(IdxVec(std::move(part1)));
79 output.emplace_back(IdxVec(std::move(part2)));
85 if (max_points <= 0) {
90 const size_t max_points_(max_points);
91 const size_t num_points =
points.GetLength();
92 if (num_points == 0) {
99 std::vector<IdxVec> partitions_to_process;
100 std::vector<IdxVec> partitions_result;
102 partitions_to_process.emplace_back(IdxVec(num_points));
103 IdxVec& indices = partitions_to_process.back();
104 std::iota(std::begin(indices), std::end(indices), 0);
107 while (partitions_to_process.size()) {
108 std::vector<IdxVec> tmp;
109 for (
auto& indices : partitions_to_process) {
110 if (indices.size() <= max_points_) {
111 partitions_result.emplace_back(IdxVec(std::move(indices)));
114 Split(points_cpu.GetDataPtr<
float>(), num_points, indices,
117 Split(points_cpu.GetDataPtr<
double>(), num_points, indices,
123 partitions_to_process.clear();
124 partitions_to_process.swap(tmp);
128 int32_t* pid_ptr = partition_id.
GetDataPtr<int32_t>();
129 for (
size_t i = 0; i < partitions_result.size(); ++i) {
130 IdxVec& indices = partitions_result[i];
131 for (
const auto idx : indices) {
132 pid_ptr[idx] = int32_t(i);
136 int num_partitions = partitions_result.size();
137 return std::tie(num_partitions, partition_id);
#define AssertTensorDtypes(tensor,...)
#define AssertTensorShape(tensor,...)
static Tensor Empty(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor with uninitialized values.
__host__ __device__ float dot(float2 a, float2 b)
std::tuple< int, core::Tensor > PCAPartition(core::Tensor &points, int max_points)
std::tuple< Eigen::Vector3d, Eigen::Matrix3d > ComputeMeanAndCovariance(const std::vector< Eigen::Vector3d > &points, const std::vector< IdxType > &indices)
Function to compute the mean and covariance matrix of a set of points.
constexpr nullopt_t nullopt
Generic file read and write utility for python interface.