SweepAndPrune的一维实现

本文详细介绍了SweepAndPrune算法在一维空间中的应用,讲解了其基本原理和实现步骤,适用于一维物理引擎中的碰撞检测。通过对物体排序和区间判断,有效地减少了碰撞检查的复杂度。
摘要由CSDN通过智能技术生成

/*
 * 实现碰撞检测中一个经典的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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值