目前大多三维化简算法对于GIS行业的倾斜模型, 非标准模型简化效果都不佳, (非闭和的三维体,俗称一张皮) 特别是三角网的边界上破洞太多, 瓦片与瓦片间有缝隙, 如下图:
本文编写了一种最简单的边界求解方法用以改进三维切片的简化破洞问题.
主要步骤如下:
首先确认判定什么是边界
再次要清除无效数据
最后标定所有顶点数据即可, 被标定的数据将在折边时候强行过滤掉, 将不会折边
示意图:(点0 是非边界的判断, 只需判断他相关的所有三角形对应的边个数是不是2, 0,1出现两次,0,2,两次0, 3两次
无效数据判定:
目前发现有以下无效数据, 三点重合的三角形, 2点重合的三角形, 对于这种直接不认为为边界,
求边界得主要代码如下:
void cache_border_order(int vi,int vj, std::map<unsigned long long, int>& maps)
{
unsigned long long vii = vi;
vii = vii << 32;
unsigned long long key1 = vii + (vj);
if (maps.find(key1) != maps.end())
{
maps[key1] = maps[key1] + 1;
}
else
{
maps[key1] = 1;
}
}
bool is_border(int vi,const std::vector<int> &ti)
{
if (ti.size() <= 2)
return true;
std::map<unsigned long long, int> tcountmap = {};
for (int i = 0; i < ti.size(); i++)
{
int a[2] = { 0,1 };
int tii = 0;
//无效三角形
if (triangles[ti[i]].v[0] == triangles[ti[i]].v[1] ||
triangles[ti[i]].v[0] == triangles[ti[i]].v[2] ||
triangles[ti[i]].v[1] == triangles[ti[i]].v[2])
continue;
for (int j = 0; j < 3; j++)
{
if (vi == triangles[ti[i]].v[j])
{
tii = j;
break;
}
}
if (tii == 2)
{
a[0] = 0;a[1] = 1;
}
else if (tii == 1)
{
a[0] = 0;a[1] = 2;
}
else if (tii == 0)
{
a[0] = 1;a[1] = 2;
}
cache_border_order(vi, triangles[ti[i]].v[a[0]], tcountmap);
cache_border_order(vi, triangles[ti[i]].v[a[1]], tcountmap);
}
for (auto it = tcountmap.begin(); it != tcountmap.end(); it++)
{
if (it->second < 2)
return true;
}
return false;
}
void simplify_mark_border()
{
for (int i = 0; i < vertices.size(); i++)
{
std::vector<int> contaions_triangles = {};
for (int j = 0; j < triangles.size(); j++)
{
//无效三角形
if (triangles[i].v[0] == triangles[i].v[1] ||
triangles[i].v[0] == triangles[i].v[2] ||
triangles[i].v[1] == triangles[i].v[2])
continue;
if (triangles[j].v[0] == i || triangles[j].v[1] == i || triangles[j].v[2] == i)
{
contaions_triangles.push_back(j);
}
}
if (is_border(i, contaions_triangles))
{
vertices[i].border = 1;
vertices[i].cannotdel = true;
//for (int j = 0; j < triangles.size(); j++)
//{
// triangles[j].cannotdel = true;
//}
}
else
{
vertices[i].border = 0;
vertices[i].cannotdel = false;
}
//if (vertices[i].border != vertices[i].candel)
//{
// printf("%d\n", i);
//}
}
最终效果:
最终和cesuimlab对比了下, 虽然效果没它好, 但是胜在简化效率高一个数据量级别;
完整代码下载链接: 三维简化的改进破洞问题-C++文档类资源-优快云下载