3D打印切片软件支撑算法研究
一、为何需要自动支撑?
3D打印与传统模具制造方式不同,3D打印是增材制造,将模型整体分割成n层,逐层打印的过程,每一层是基于上一层的基础之上的累加。目前根据设备机构主要分为以下几个大类:FDM,LCD,SLM,SLA,DLP。
其中:
FDM也称耗材3d打印,主要材料为pla,abs等,如创想三维、anycubic,目前消费级机型售价大概1500–3000之间,各种变种,如最新比较潜力的“发光字打印机”、以水泥为打印材料,多彩色打印(以磨合为辅助,切片时记录纹理信息)
LCD为两年前开始出现的机型,属于光固化系列,材料为光敏树脂,精度比FDM高很多,可以打印的很精细,市面低端1500–3000如anycubic,浙江锐辰等,高端的上万元或以上,如Preform,诺瓦智能,金达雷等,目前局限是打印尺寸小,以及分辨率大多数为2k,少部分企业正在尝试4k屏,如能顺利即可解决水波纹、大尺寸等问题,将是一个新的提升
SLM为金属粉末烧结技术,材料为金属,精度非常高,可打印航空材料,都是有钱的大公司才会研发这样的设备,如先临
SLA激光束在液态树脂表面勾画出物体形状,层层打印出模型,速度比较慢,但精度较高,成本也较大,大公司sla设备以极光尔沃、大族激光等为主
DLP和LCD类似,但比LCD精度更高,利用数字光投影技术,目前成本较大,感兴趣的可具体去了解
为何要支撑?
3d打印,逐层累加,就无法避免层突变,即悬空打印,上一层无材料的情况下,突变当前层,无支撑时必然会“掉”到工作平台之上,导致打印失败。
- 1、解决悬空的情况。
- 2、防止特有的几何面被破坏,故意抬升添加支撑
- 3、保持横截面变化均匀,受力均匀,以免模型内应力导致模型变形
二、扫描待支撑的区域
目前待打印模型多数为stl、obj、3mf等数字化模型文件,都是以三角面片为载体记录模型信息,模型文件的可视化效果如下:
自动支撑常规步骤:
- 1、检测模型的最低点
- 2、检测模型的最低边
- 3、检测法向量朝下的悬空面片
- 4、对悬空面进行分区域处理
- 5、对每个区域进行xy平面投影
- 6、用栅格划分投影平面,然后得到栅格交点
- 7、将交点利用重心坐标映射回模型的面片中
- 8、将最低点+最低边+采样点组合为最终的支撑点
- 9、生成支撑结构(如垂直结构、树状结构等)
检测模型的最低点:
int vn=mesh.vertexs.size();
for(int i=0;i<vn;i++)
{
vector<int>neibors=mesh.neibors[i];
vec vi=mesh.vertexs[i];
int n=neibors.size();
bool is_min_p=true;
for(int j=0;j<n;j++)
{
int id=neibors[j];
vec vj=mesh.vertexs[id];
if(vi[2]>=vj[2])
{
is_min_p=false;
break;
}
}
if(is_min_p)
{
vertex_list.push_back(vi);
}
}
float angle=45*PI/180;
vec fn0=mesh.facenormal[i];
vec fn1=mesh.facenormal[j];
vec en=fn0+fn1;
normalize(en);
if(en DOT vec(0,0,1)<0)
{
vec v0=mesh.vertexs[id0];
vec v1=mesh.vertexs[id1];
vec vp=v0-v1;
float l0=len(vp);
vp[2]=0;
float l1=len(vp);
float theta=acos(l1/l0);
if(theta<angle)
{
edges_lists.push_back(eid);
}
}
int fn=mesh.faces.size();
for(int i=0;i<fn;i++)
{
vec fn=mesh.facenormal[i];
if(fn DOT vec(0,0,1)<0)
{
face_lists.push_back(i);
}
}
分区域:
set<int>flist;
set<int>check_flags;
vector<vector<int>>regionset;
for(auto item:face_lists)flist.insert(item);
while(!flist.empty())
{
vector<int>region;
queue<int> Q;
auto it=flist.begin();
Q.push(*it);
check_flags.inset(*it);
flist.erase(it);
while(!Q.empty())
{
int id=Q.front();
Q.pop();
region.push_back(id);
Face f=mesh.faces[id];
for(int i=0;i<3;i++)
{
int vid=f[i];
vector<int>adsf=mesh.adjfaces[vid];
for(auto fid:adsf)
{
auto itf=check_flags.find(fid);
if(itf!=check_flags.end())continue;
auto itlst=flist.find(fid);
if(itlst!=flist.end())
{
flist.erase(itlsl);
Q.push(fid);
}
}
}
}
if(region.empty())continue;
regionset.push_back(region);
}
采样点重映射回网格
float step=2;
int fn=region.size();
for(int i=0;i<fn;i++)
{
auto f=mesh.faces[i];
auto&v0=mesh.vertexs[f[0]];
auto&v1=mesh.vertexs[f[1]];
auto&v2=mesh.vertexs[f[2]];
int minx=min(min(v0[0],v1[0]),v2[0]);
int miny=min(min(v0[1],v1[1]),v2[1]);
int maxx=max(max(v0[0],v1[0]),v2[0]);
int maxy=max(max(v0[1],v1[1]),v2[1]);
int xsid=floor((minx-mesh.min[0])/step);
int ysid=floor((miny-mesh.min[1])/step);
int xeid=floor((maxx-mesh.min[0])/step)+1;
int yeid=floor((maxy-mesh.min[1])/step)+1;
for(auto n=xsid;n<=xeid;n++)
for(auto m=ysid;m<=yeid;m++)
{
vec v(mesh.min[0]+xsid*step,mesh.min[1]+ysid*step,0);
flaot a,b,c;
if(Point2DTo3D(v0,v1,v2,v,a,b,c))
{
vec p=a*v0+b*v1+c*v2;
sample_lists.push_back(p);
}
}
}
三、生成支撑结构
支撑结构分多种,最常用的就是垂直方式,也有树状结构。垂直结构,比较牢固,但比较耗材,支撑也是成本。树状支撑比较省成本,但算法计算复杂,越往下根越少,趋于稀疏。
四、自动支撑的局限与难点
- 1、无法根据人为经验判断该处是否添加支撑
- 2、复杂拓补结构的网格支撑非常困难
- 3、建立网格拓补关系需要大量的内存消耗,大模型加支撑非常吃力,并导致渲染系统卡顿
- 4、复杂模型的支撑碰撞检测相当繁琐
- 5、支撑密度根据不同类型模型控制较为繁琐,需要不断测试,并无最合适的密度参数
- 6、栅格采样法,会错过很多细小的特征,step跨度越大,错过概率越大,导致有些模型恰好都错过面片,支撑失败。后续升级为更好的支撑算法,支撑效果更理想。