Example #1
0
AbstractKDNode *KDTree::Build(__in std::vector<Triangle const *> const &set,
                              __in float3_t const &min,
                              __in float3_t const &max,
                              __in std::size_t depth) {
    if ((set.size() <= max_bucket_size_) || (depth > max_hierarchy_depth_)) {
        // std::tcerr << set.size();

        if (set.empty()) {
            return new KDNull();
        } else {
            return new KDLeaf(set);
        }
    }
    depth++;

    float3_t const range(max - min);

    std::size_t axis = ~0U;  // 分割次元
    float_t value = std::numeric_limits<float_t>::signaling_NaN();  // 分割位置

    // surface area heuristic
    float_t min_cost = std::numeric_limits<float_t>::max();

    // event
    struct open_close_event {
        bool operator<(open_close_event const &e) const {
            // value が等しい場合 open Event < close Event とする
            return (value < e.value) ? true : (value > e.value) ? false
                   : type < e.type;
        }

        bool type;  // event type: {false: open, true: close}
        float_t value;
    };

#define EVENT_UPDATE(v)                                         \
  {                                                             \
    float_t const r = v - min[k];                               \
    float_t const sa_left = a + b * r;                          \
    float_t const sa_right = a + b * (range[k] - r);            \
    float_t const cost = n_left * sa_left + n_right * sa_right; \
    if (min_cost > cost) {                                      \
      min_cost = cost;                                          \
      axis = k;                                                 \
      value = v;                                                \
    }                                                           \
  }

    std::vector<open_close_event> event_list(set.size() * 2);
    for (std::size_t k = 0; k < 3; ++k) {
        // init event list
        for (std::size_t i = 0, size = set.size(); i < size; ++i) {
            event_list[i].type = false;
            event_list[i].value = set[i]->min(k);  // 最小値
            event_list[i + size].type = true;
            event_list[i + size].value = set[i]->max(k) + EPSILON;  // 最大値
        }

        // sort event list
        std::sort(event_list.begin(), event_list.end());

        // compute min cost
        float_t const a = range[(k + 1) % 3] * range[(k + 2) % 3];
        float_t const b = range[(k + 1) % 3] + range[(k + 2) % 3];

        std::size_t n_left = 0;
        std::size_t n_right = set.size();
        {
            float_t const v = event_list[0].value - EPSILON;
            EVENT_UPDATE(v);
        }
        for (std::size_t i = 0, size = event_list.size(); i < size; ++i) {
            if (event_list[i].type) {
                n_right--;  // close event
            } else {
                n_left++;  // open event
            }

            float_t v = event_list[i].value;
            if ((i + 1) < size) {
                if (v == event_list[i + 1].value) {
                    continue;  // do not evalute
                }
                // v += (event_list[i+1].value - v) * float_t(0.5);
            } else {
                v += EPSILON;
            }

            EVENT_UPDATE(v);
        }
    }
#undef EVENT_UPDATE

    // 左右に分類
    std::vector<Triangle const *> set_left;
    std::vector<Triangle const *> set_right;

    for (std::size_t i = 0, size = set.size(); i < size; ++i) {
        switch (set[i]->Overlap(axis, value)) {
        case 1:
            set_left.push_back(set[i]);
            break;  // 左
        case 2:
            set_right.push_back(set[i]);
            break;  // 右
        case 3:
            set_left.push_back(set[i]);
            set_right.push_back(set[i]);
            break;  // 両方
        default:
            assert(!"bad Triangle::Overlap");
            break;
        }
    }

    // set.swap(std::vector<Triangle const *>()); // clear & trim

    // create nodes
    KDNode *node = new KDNode(axis, value);
    {
        float3_t max_left(max);
        max_left[axis] = value;
        node->SetChild(0, Build(set_left, min, max_left, depth));
    }
    {
        float3_t min_right(min);
        min_right[axis] = value;
        node->SetChild(1, Build(set_right, min_right, max, depth));
    }

    return node;
}
Example #2
0
void Localization::voxelizeCloud(const PointCloud::Ptr& cloud_in, const Eigen::VectorXi& pts_cam_source_in,
	PointCloud::Ptr& cloud_out, Eigen::VectorXi& pts_cam_source_out, double cell_size)
{
	Eigen::Vector3d min_left, min_right;
	min_left << 10000, 10000, 10000;
	min_right << 10000, 10000, 10000;
	Eigen::Matrix3Xd pts(3, cloud_in->points.size());
	int num_left = 0;
	int num_right = 0;
	for (int i = 0; i < cloud_in->points.size(); i++)
	{
		if (pts_cam_source_in(i) == 0)
		{
			if (cloud_in->points[i].x < min_left(0))
				min_left(0) = cloud_in->points[i].x;
			if (cloud_in->points[i].y < min_left(1))
				min_left(1) = cloud_in->points[i].y;
			if (cloud_in->points[i].z < min_left(2))
				min_left(2) = cloud_in->points[i].z;
			num_left++;
		}
		else if (pts_cam_source_in(i) == 1)
		{
			if (cloud_in->points[i].x < min_right(0))
				min_right(0) = cloud_in->points[i].x;
			if (cloud_in->points[i].y < min_right(1))
				min_right(1) = cloud_in->points[i].y;
			if (cloud_in->points[i].z < min_right(2))
				min_right(2) = cloud_in->points[i].z;
			num_right++;
		}
		pts.col(i) = cloud_in->points[i].getVector3fMap().cast<double>();
	}

	// find the cell that each point falls into
	std::set<Eigen::Vector3i, Localization::UniqueVectorComparator> bins_left;
	std::set<Eigen::Vector3i, Localization::UniqueVectorComparator> bins_right;
	int prev;
	for (int i = 0; i < pts.cols(); i++)
	{
		if (pts_cam_source_in(i) == 0)
		{
			Eigen::Vector3i v = floorVector((pts.col(i) - min_left) / cell_size);
			bins_left.insert(v);
			prev = bins_left.size();
		}
		else if (pts_cam_source_in(i) == 1)
		{
			Eigen::Vector3i v = floorVector((pts.col(i) - min_right) / cell_size);
			bins_right.insert(v);
		}
	}

	// calculate the cell values
	Eigen::Matrix3Xd voxels_left(3, bins_left.size());
	Eigen::Matrix3Xd voxels_right(3, bins_right.size());
	int i = 0;
	for (std::set<Eigen::Vector3i, Localization::UniqueVectorComparator>::iterator it = bins_left.begin();
			it != bins_left.end(); it++)
	{
		voxels_left.col(i) = (*it).cast<double>();
		i++;
	}
	i = 0;
	for (std::set<Eigen::Vector3i, Localization::UniqueVectorComparator>::iterator it = bins_right.begin();
			it != bins_right.end(); it++)
	{
		voxels_right.col(i) = (*it).cast<double>();
		i++;
	}

	voxels_left.row(0) = voxels_left.row(0) * cell_size
			+ Eigen::VectorXd::Ones(voxels_left.cols()) * min_left(0);
	voxels_left.row(1) = voxels_left.row(1) * cell_size
			+ Eigen::VectorXd::Ones(voxels_left.cols()) * min_left(1);
	voxels_left.row(2) = voxels_left.row(2) * cell_size
			+ Eigen::VectorXd::Ones(voxels_left.cols()) * min_left(2);
	voxels_right.row(0) = voxels_right.row(0) * cell_size
			+ Eigen::VectorXd::Ones(voxels_right.cols()) * min_right(0);
	voxels_right.row(1) = voxels_right.row(1) * cell_size
			+ Eigen::VectorXd::Ones(voxels_right.cols()) * min_right(1);
	voxels_right.row(2) = voxels_right.row(2) * cell_size
			+ Eigen::VectorXd::Ones(voxels_right.cols()) * min_right(2);

	PointCloud::Ptr cloud(new PointCloud);
	cloud->resize(bins_left.size() + bins_right.size());
	Eigen::VectorXi pts_cam_source(bins_left.size() + bins_right.size());
	for (int i = 0; i < bins_left.size(); i++)
	{
		pcl::PointXYZ p;
		p.x = voxels_left(0, i);
		p.y = voxels_left(1, i);
		p.z = voxels_left(2, i);
		cloud->points[i] = p;
		pts_cam_source(i) = 0;
	}
	for (int i = 0; i < bins_right.size(); i++)
	{
		pcl::PointXYZ p;
		p.x = voxels_right(0, i);
		p.y = voxels_right(1, i);
		p.z = voxels_right(2, i);
		cloud->points[bins_left.size() + i] = p;
		pts_cam_source(bins_left.size() + i) = 1;
	}

	cloud_out = cloud;
	pts_cam_source_out = pts_cam_source;
}