这是以二进制模式打印的 C 代码。调用函数是:
stl_write_binary(X, Y, path)
其中 X 是 3xM 顶点矩阵,Y 是 3xN 面矩阵。两者都在 OpenCV 的 Mat 结构中。
Path 是存储 STL 文件的路径,您可以根据需要对其进行修改。
整个代码是:
int stl_write_binary(Mat &vertemp, Mat &faces, PathToFolders &path)
{
Mat vertices(vertemp.cols,vertemp.rows,vertemp.type());
vertices = vertemp.t();
cv::Mat** facets = new cv::Mat*[faces.rows];
for(int i = 0; i < faces.rows; i++)
{
facets[i] = new cv::Mat(3,4,CV_32F);
for(int j = 0; j < 3; j++)
{
vertices(Range::all(),Range(faces.at<int>(i,j),faces.at<int>(i,j)+1)).convertTo((*(facets[i]))(Range::all(),Range(j+1,j+2)), CV_32F);
}
}
//Compute their normals
Mat V1(3,faces.rows,CV_32F);
Mat V2(3,faces.rows,CV_32F);
for(int i = 0; i < faces.rows; i++)
{
V1(Range::all(),Range(i,i+1)) = ((*(facets[i]))(Range::all(),Range(2,3))) - ((*(facets[i]))(Range::all(),Range(1,2)));
V2(Range::all(),Range(i,i+1)) = ((*(facets[i]))(Range::all(),Range(3,4))) - ((*(facets[i]))(Range::all(),Range(1,2)));
}
Mat V3(3,faces.rows,CV_32F);
Mat V4(3,faces.rows,CV_32F);
Mat V5(3,faces.rows,CV_32F);
Mat V6(3,faces.rows,CV_32F);
V1(Range(1,2),Range::all()).copyTo(V3(Range(0,1),Range::all()));
V1(Range(2,3),Range::all()).copyTo(V3(Range(1,2),Range::all()));
V1(Range(0,1),Range::all()).copyTo(V3(Range(2,3),Range::all()));
V2(Range(2,3),Range::all()).copyTo(V4(Range(0,1),Range::all()));
V2(Range(0,1),Range::all()).copyTo(V4(Range(1,2),Range::all()));
V2(Range(1,2),Range::all()).copyTo(V4(Range(2,3),Range::all()));
V2(Range(1,2),Range::all()).copyTo(V5(Range(0,1),Range::all()));
V2(Range(2,3),Range::all()).copyTo(V5(Range(1,2),Range::all()));
V2(Range(0,1),Range::all()).copyTo(V5(Range(2,3),Range::all()));
V1(Range(2,3),Range::all()).copyTo(V6(Range(0,1),Range::all()));
V1(Range(0,1),Range::all()).copyTo(V6(Range(1,2),Range::all()));
V1(Range(1,2),Range::all()).copyTo(V6(Range(2,3),Range::all()));
Mat normals(3,faces.rows,CV_32F);
normals = V3.mul(V4) - V5.mul(V6);
V1.release();
V2.release();
V3.release();
V4.release();
V5.release();
V6.release();
Mat normalsqu(3,faces.rows,CV_32F);
Mat normalsqu_colm_summed(1,faces.rows,CV_32F);
normalsqu = normals.mul(normals);
cv::reduce(normalsqu, normalsqu_colm_summed, 0, CV_REDUCE_SUM, CV_32F);
cv::sqrt(normalsqu_colm_summed,normalsqu_colm_summed);//check mem leak
normalsqu.release();
normalsqu_colm_summed = 1/normalsqu_colm_summed;
for(int i = 0; i < faces.rows; i++)
{
normals(Range::all(),Range(i,i+1)) = normals(Range::all(),Range(i,i+1)) * normalsqu_colm_summed.at<float>(i);
}
normalsqu_colm_summed.release();
for(int i = 0; i < faces.rows; i++)
{
normals(Range::all(),Range(i,i+1)).copyTo(((*(facets[i]))(Range::all(),Range(0,1))));
}
normals.release();
//write to stl file
//get file paths
std::vector<std::string> masktoken;
split(path.pathtoimages, '/', masktoken);
path.pathtoSTL = path.pathtoSTL+masktoken[0];
for(int i = 1; i < masktoken.size()-1; i++)
{
path.pathtoSTL = path.pathtoSTL+"/"+masktoken[i];
}
path.pathtoSTL = path.pathtoSTL+"/"+"mesh.stl";
cout<<"Saving file to "<<path.pathtoSTL<<endl;
const char * c = path.pathtoSTL.c_str();
ofstream pFile;
pFile.open (c, ios::out | ios::binary);
if (pFile.is_open())
{
string name = "Create by stlwrite.m ";
name = name + currentDateTime();
pFile.setf(ios::left);
pFile.width(sizeof(unsigned char)*80);
//header
pFile << name;
unsigned int size = faces.rows;
//size
pFile.write((char*)&size,sizeof(size));
int height = (*facets[0]).rows * (*facets[0]).cols * 2 + 1;
unsigned short ** data= new unsigned short *[height];
for(int i = 0; i < height; i++)
{
data[i] = new unsigned short[faces.rows];
}
for(int j = 0; j < faces.rows; j++)
{
int i = 0;
//for one facets
for(int k = 0; k < (*facets[j]).cols; k++)
{
for(int l = 0; l < (*facets[j]).rows; l++)
{
float f = (*facets[j]).at<float>(l,k);
data[i][j] = *reinterpret_cast<unsigned int *>(&f);
data[i+1][j] = *reinterpret_cast<unsigned int *>(&f)>>16;
i = i + 2;
}
}
//then for the last row
data[height-1][j] = (unsigned short)0;
}
for (int i = 0; i < faces.rows; i++)
for (int j = 0; j < height; j++)
pFile.write ((char*)&data[j][i], sizeof(unsigned short) );
pFile.close();
//fclose (pFile);
//delete table
for(int i = 0; i < height; i++)
{
delete[] data[i];
}
delete[] data;
}else{
cout<<"stlwrite:cannotWriteFile"<<" "<<"Unable to write to"<<" "<<path.pathtoSTL<<endl;
}
for(int i = 0; i < faces.rows; i++)
{
(*facets[i]).release();
}
delete[] facets;
return 1;
}