将stl文件中vertex顶点由顺时针(clockwise)排列改为逆时针(counterclockwise)

ⅰ亾dé卋堺 提交于 2020-01-27 02:14:21

最近需要读取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

对比发现面法向量大小并未发生变化。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!