SweepAndPrune的一维实现

SweepAndPrune的一维实现

/*
 * 实现碰撞检测中一个经典的Sweep And Prune算法
 * 参考文章:D. Baraff (Ph. D thesis), p 52.
 * http://www.cs.cmu.edu/~baraff/papers/thesis-part1.ps.Z
 */

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <algorithm>

void sweepAndPrune(std::vector<std::tuple<bool, unsigned int, double>> values, std::map<unsigned int, std::list<unsigned int>> &collision)
{
	// 根据区间端点位置对各个区间端点进行排序
	std::sort(values.begin(), values.end(), [](std::tuple<bool, unsigned int, double> a, std::tuple<bool, unsigned int, double> b) { return std::get<2>(a) < std::get<2>(b); });
	// 输出排序之后的结果
	for (auto ite = values.begin(); ite != values.end(); ite++)
	{
		auto t = std::get<0>(*ite) ? "b" : "e";
		auto idx = std::get<1>(*ite);
		std::cout << idx << "," << t << ": " << std::get<2>(*ite) << std::endl;
	}
	std::list<unsigned int> activeList = {};
	// 遍历区间端点,生成每个区间对应的重叠区间列表。如果区间端点为起始点,那么就activeList中的区间索引就是该区间的重叠区间,并将该区间添加到activeList中
	// 否则就在activeList中删除该区间索引
	for (auto ite = values.begin(); ite != values.end(); ite++)
	{
		auto idx = std::get<1>(*ite);
		if (std::get<0>(*ite)) // b
		{
			collision[idx] = activeList;
			activeList.push_back(idx);
		}
		else // e
		{
			activeList.remove(idx);
		}
	}

}

int main()
{
	// 在一个坐标轴上的多个区间
	std::vector<std::pair<double, double>> interal = { {3.0,5.0},{7.0,18.0},{0.0,8.0},{10.0,16.0},{6.0,12.0},{1.0,4.0} };
	for (auto ite = interal.begin(); ite != interal.end(); ite++)
	{
		std::cout << "[" << ite->first << "," << ite->second << "]\n";
	}
	// 保存每个区间端点是否为起始点(b:true, e:false),索引值,位置
	std::vector<std::tuple<bool,unsigned int, double>> values;
	for (unsigned int i = 0; i < interal.size(); i++)
	{
		values.push_back({ true, i,interal[i].first });
		values.push_back({ false,i,interal[i].second });
	}
	std::map<unsigned int, std::list<unsigned int>> collision;
	sweepAndPrune(values, collision);
	// 输出具有重叠的线段
	for (auto ite = collision.begin(); ite != collision.end(); ite++)
	{
		std::cout << "the " << ite->first + 1<< "th segment is overlapping with segments: ";
		for (auto i : ite->second)
		{
			std::cout << i + 1 <<",";
		}
		std::cout << "."<<std::endl;
	}
	return 0;
}

 

上一篇:【2021寒假】待办事项一览


下一篇:补题记录:E. Correct Placement