|
大家好,分享一个几何算法思路,欢迎提出更优的方法!
一、问题:用一个线段集切割一个多边形,得到多个切割后的多边形。将其看成以点为节点的图结构,依次搜索最小的闭合区域。
三、算法思路:
1 所有线段求相交,得到所有点,并根据点和点之间的连接关系,得到有向图 (双向连接)
vector<Point> AllPts;//所有的交点
map<int,vector<int>> Graph;//有向图,key为节点下标,value为和其相连的点
2 去掉所有悬空的线段(出度数+入度数<2)
3 根据连通情况,将原始图划分为多个连通图(可用Union-Find算法)
4 下面以一个连通图为研究对象,其实就是求最小的闭合区域:
5 首先寻找外轮廓,
auto LeftEdgePoint = FindLeftPoint(AllPts);//找到最左点
vector<int> OutlinePath = FindClosedPath(Graph);//以最左点为起点,寻找外轮廓,结束条件为路径包含所有线段
DeletePath(Graph,OutlinePath);//查找成功后,将查找到的连通关系从连通图中删除,得到如下的关系
6 寻找最小闭合路径,直到所有节点被删掉
while(!Graph.IsEmpty())
{
auto startPt = AllPts[Graph.First()];//找任意点为起点
vector<int> OutlinePath = FindClosedPath(Graph);//寻找闭合轮廓,结束条件为路径不包含任何线段
DeletePath(Graph,OutlinePath);//查找成功后,将连通关系从连通图中删除
}//算法结束
7 FindClosedPath是核心函数,即在连通图中找到合法的闭合路径,可用回溯法
vector<int> path;
bool backTrack(int node){
if(IsValidPath()) return true;//结束条件:路径闭合(nextPoint为path的起始点),并且不包含任何其他线段
vector<int> links = Graph[node];//下一个节点
foreach(auto link in links){//搜索可能性
if(path.contains(link))continue;//不能回头
path.push_back(link);//尝试可能性
if(backTrack(link)) return true;//如果找到了,则返回
path.Remove(path.end());//回溯
}
return false;
}
[code]原文链接:https://blog.csdn.net/Time2017/article/details/112846614[/code] |
|