最近需要读取solidWork
软件生成的复杂几何体(stl格式),用于识别一系列点位于复杂几何体内部还是外部,发现识别函数需要stl文件符合右手规则
,即点的排布要逆时针顺序,而且法线方向朝外,但是solidWork生成的文件不符合这个特征,所以写了一个c++
的小程序,用来实现该过程,具体内容如下:
1. stl文件格式:
facet normal -0.996195 0.0871562 -0
outer loop
vertex -7.500000e-002 -1.836970e-017 2.220404e+000 //p1
vertex -7.500000e-002 -1.836970e-017 9.964039e-001 //p2
vertex -7.386058e-002 1.302361e-002 2.220404e+000 //p3
endloop
endfacet
上述代码块即为stl文件的格式,主要由面法向量,以及3个点构成,3个点连线顺序不符合右手规则
,我们可以调p2,p3
的顺序,并重新求解facet normal即可,求解方法可以参考该链接
2. 具体实现
1.对原有stl文件进行分割:
#include<vector>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstring>
using namespace std;
int main(int argc, char *argv[])
{
std::fstream fin;
fin.open("sum.stl");
std::vector<string> v;
string tmp;
while(std::getline(fin,tmp))
{
v.push_back(tmp);
}
ofstream outVertex_a("stlVertex_a.src",std::ios::app);
ofstream outVertex_b("stlVertex_b.src",std::ios::app);
ofstream outVertex_c("stlVertex_c.src",std::ios::app);
if(outVertex_a.fail()){
cout<<"output outVertex_a fail!"<<endl;
}
int index = 0;
for(std::vector<std::string>::iterator i = v.begin();i!=v.end();i++){
index++;
string tmp = *i;
if(index%7 == 3 ){
outVertex_a<<tmp<<'\n';
}else if (index%7 == 4){
outVertex_b<<tmp<<'\n';
}else if (index%7 == 5){
outVertex_c<<tmp<<'\n';
}
}
outVertex_a.close();
outVertex_b.close();
outVertex_c.close();
return 0;
}
需要注意的是,要修改的文件需重命名为sum.stl
,而且需要手动删除生成的stlVertex-*.src
文件中行首的vertex
单词,方便后续直接读入。
2. 文件转换:
#include<vector>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstring>
using namespace std;
int main(int argc, char *argv[])
{
std::fstream fin;
fin.open("sum.stl");
std::vector<string> v;
string tmp;
while(std::getline(fin,tmp))
{
v.push_back(tmp);
}
ofstream outStl("part1.stl",std::ios::app);
if(outStl.fail()){
cout<<"output outStl fail!"<<endl;
}
FILE * finXYZ_a = fopen("stlVertex_a.src","r");
FILE * finXYZ_b = fopen("stlVertex_b.src","r");
FILE * finXYZ_c = fopen("stlVertex_c.src","r");
float p1_x = 0.0;
float p1_y = 0.0;
float p1_z = 0.0;
float p2_x = 0.0;
float p2_y = 0.0;
float p2_z = 0.0;
float p3_x = 0.0;
float p3_y = 0.0;
float p3_z = 0.0;
int index2 = 0;
outStl<<"solid part1"<<'\n';
for(std::vector<std::string>::iterator i = v.begin();i!=v.end();i++){
index2++;
string tmp = *i;
if(index2%7 == 1){
fscanf(finXYZ_a,"%f %f %f",&p1_x,&p1_y,&p1_z);
fscanf(finXYZ_b,"%f %f %f",&p2_x,&p2_y,&p2_z);
fscanf(finXYZ_c,"%f %f %f",&p3_x,&p3_y,&p3_z);
cout<<"a = ("<<p1_x<<","<<p1_y<<","<<p1_z<<")"<<endl;
cout<<"b = ("<<p2_x<<","<<p2_y<<","<<p2_z<<")"<<endl;
cout<<"c = ("<<p3_x<<","<<p3_y<<","<<p3_z<<")"<<endl;
float a1 = p2_x -p1_x;
float b1 = p2_y -p1_y;
float c1 = p2_z -p1_z;
float a2 = p3_x -p1_x;
float b2 = p3_y -p1_y;
float c2 = p3_z -p1_z;
float a = b1 * c2 - b2 * c1;
float b = a2 * c1 - a1 * c2;
float c = a1 * b2 - b1 * a2;
float normal_a = sqrt(a*a+b*b+c*c);
a /= normal_a;
b /= normal_a;
c /= normal_a;
outStl<<"facet normal "<<a<<" "<<b<<" "<<c<<"\n";
}
else if(index2%7 == 3){
outStl<<" vertex "<<p1_x<<" "<<p1_y<<" "<<p1_z<<"\n";
}else if(index2%7 == 4){
outStl<<" vertex "<<p3_x<<" "<<p3_y<<" "<<p3_z<<"\n";
}else if(index2%7 == 5){
outStl<<" vertex "<<p2_x<<" "<<p2_y<<" "<<p2_z<<"\n";
}else{
outStl<<tmp<<'\n';
}
}
outStl<<"endsolid part1"<<'\n';
outStl.close();
fclose(finXYZ_a);
fin.close();
return 0;
}
生成的part1.stl
文件即为目标文件
3.结果展示:
转换前:
facet normal -0.996195 0.0871562 -0
outer loop
vertex -7.500000e-002 -1.836970e-017 2.220404e+000
vertex -7.500000e-002 -1.836970e-017 9.964039e-001
vertex -7.386058e-002 1.302361e-002 2.220404e+000
endloop
endfacet
转换后:
solid part1
facet normal -0.996195 0.0871562 -0
outer loop
vertex -0.075 -1.83697e-17 2.2204
vertex -0.0738606 0.0130236 2.2204
vertex -0.075 -1.83697e-17 0.996404
endloop
endfacet
对比发现面法向量大小并未发生变化。
来源:CSDN
作者:zhaopeng162
链接:https://blog.csdn.net/zhaopeng162/article/details/103896723