//xlFileStream.h
#pragma once
#include <Windows.h>
#include <tchar.h>
//xlFileStream.h
struct FileHeader
{
wchar_t Author[32]; // 文件的创建人
wchar_t Company[32]; // 创建人的单位
char Version[34]; // GUID,表示版本
unsigned int Count; // 所含Node的数量
char Reserved[90]; // 保留字节
};
class FileStream
{
private:
HANDLE m_hFile;
bool m_bTmpFile;
char* __Version__;
public:
void Close( )
{
CloseHandle( m_hFile );
m_hFile = NULL;
}
bool CreateFile( const wchar_t lpwszPathName[] )
{
if(m_bTmpFile)
m_hFile = ::CreateFile(lpwszPathName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
else
m_hFile = ::CreateFile(lpwszPathName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(m_hFile == INVALID_HANDLE_VALUE)
{
m_hFile = NULL;
return false;
}
return true;
}
bool OpenFile( const wchar_t lpwszPathName[] )
{
if(m_bTmpFile)
m_hFile = ::CreateFile(lpwszPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
else
m_hFile = ::CreateFile(lpwszPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(m_hFile == INVALID_HANDLE_VALUE)
{
m_hFile = NULL;
return false;
}
return true;
}
BOOL Read( void* pv, ULONG cb, LPOVERLAPPED lpOverlapped = NULL)
{
ULONG pcbRead;
BOOL bRet = ReadFile(m_hFile, pv, cb, &pcbRead, lpOverlapped);
if(!bRet)
return false;
if(cb != pcbRead)
return false;
else
return true;
}
BOOL Write( void const* pv, ULONG cb, LPOVERLAPPED lpOverlapped = NULL)
{
ULONG pcbWritten;
BOOL bRet = WriteFile(m_hFile, pv, cb, &pcbWritten, lpOverlapped);
if(!bRet)
return false;
if(cb != pcbWritten)
return false;
else
return true;
}
bool WriteHeader(unsigned int Count, wchar_t Author[] = NULL, wchar_t Company[] = NULL)
{
FileHeader header;
if(Author != NULL)
wcscpy_s(header.Author, wcslen(Author) + 1, Author);
if(Company != NULL)
wcscpy_s(header.Company, wcslen(Company) + 1, Company);
strcpy_s(header.Version, 34, __Version__);
header.Count = Count;
BOOL bRet = Write(&header, sizeof(FileHeader));
if(!bRet)
return false;
return true;
}
bool ReadHeader(unsigned int& Count, wchar_t Author[] = NULL, wchar_t Company[] = NULL)
{
FileHeader header;
if(Read(&header, sizeof(FileHeader)))
{
if(Author != NULL)
wcscpy_s(Author, wcslen(header.Author) + 1, header.Author);
if(Company != NULL)
wcscpy_s(Company, wcslen(header.Company) + 1, header.Company);
Count = header.Count;
if(strncmp(__Version__, header.Version, 32) != 0)
false;
}
return true;
}
public:
FileStream( bool bTmpFile = false ) : m_hFile(0), m_bTmpFile(bTmpFile)
{
__Version__ = "691287C840924b6aB3C98F8C278FF967";
}
~FileStream( void )
{
CloseHandle( m_hFile );
}
};
xlSortPoints.h
// xlSortPoints.h
// 用于完成空间点的最小堆算法,具体的
#pragma once
#include <math.h>
#include <float.h>
#include <vector>
#include <map>
using namespace std;
namespace SortPoint
{
struct tagIndex { int i; int j; int k; };
inline bool operator < (const tagIndex& ind1, const tagIndex& ind2)
{
if(ind1.i < ind2.i) return true;
else if(ind1.i > ind2.i) return false;
else if(ind1.j < ind2.j) return true;
else if(ind1.j > ind2.j) return false;
else if(ind1.k < ind2.k) return true;
else return false;
}
inline bool operator > (const tagIndex& ind1, const tagIndex& ind2)
{
if(ind1.i > ind2.i) return true;
else if(ind1.i < ind2.i) return false;
else if(ind1.j > ind2.j) return true;
else if(ind1.j < ind2.j) return false;
else if(ind1.k > ind2.k) return true;
else return false;
}
inline bool operator == (const tagIndex& ind1, const tagIndex& ind2)
{
if(ind1 < ind2) return false;
else if(ind1 > ind2) return false;
else return true;
}
template<typename Real>
class CSortPoints
{
private:
map<tagIndex, vector<int>> m_mapSortedPoints;
Real m_fOrg[3];
Real m_fUnit;
Real m_fMinDist;
inline void GetIndex(const Real point[3], tagIndex& ind)
{
ind.i = int((point[0] - m_fOrg[0]) / m_fUnit);
ind.j = int((point[1] - m_fOrg[1]) / m_fUnit);
ind.k = int((point[2] - m_fOrg[2]) / m_fUnit);
}
public:
inline int insert_point(Real pt[3], vector<Real>& points)
{
size_t i;
int index;
tagIndex ind, tmp;
GetIndex(pt, ind);
map<tagIndex, vector<int>>::iterator iter;
for(tmp.i = ind.i - 1; tmp.i < ind.i + 2; tmp.i++)
{
for(tmp.j = ind.j - 1; tmp.j < ind.j + 2; tmp.j++)
{
for(tmp.k = ind.k - 1; tmp.k < ind.k + 2; tmp.k++)
{
iter = m_mapSortedPoints.find(tmp);
if(iter != m_mapSortedPoints.end())
{
vector<int>& bucket = m_mapSortedPoints[tmp];
for(i = 0; i < bucket.size(); i++)
{
index = bucket[i] * 3;
if( (fabs(points[index + 0] - pt[0]) < m_fMinDist) &&
(fabs(points[index + 1] - pt[1]) < m_fMinDist) &&
(fabs(points[index + 2] - pt[2]) < m_fMinDist) )
{
return bucket[i];
}
}
}
}
}
}
int ret = points.size() / 3;
points.push_back(pt[0]);
points.push_back(pt[1]);
points.push_back(pt[2]);
m_mapSortedPoints[ind].push_back(ret);
return ret;
}
inline int NearestPoint(const vector<Real>& points, Real pt[])
{
tagIndex ind, tmp;
GetIndex(pt, ind);
size_t i;
Real min = FLT_MAX;
int ret = -1, index;
map<tagIndex, vector<int>>::iterator iter;
for(tmp.i = ind.i - 1; tmp.i < ind.i + 2; tmp.i++)
{
for(tmp.j = ind.j - 1; tmp.j < ind.j + 2; tmp.j++)
{
for(tmp.k = ind.k - 1; tmp.k < ind.k + 2; tmp.k++)
{
iter = m_mapSortedPoints.find(tmp);
if(iter != m_mapSortedPoints.end())
{
vector<int>& bucket = m_mapSortedPoints[tmp];
for(i = 0; i < bucket.size(); i++)
{
index = bucket[i] * 3;
Real dist = pow(points[index + 0] - pt[0], 2) + pow(points[index + 1] - pt[1], 2) +
pow(points[index + 2] - pt[2], 2);
if(dist < min)
{
min = dist;
ret = index;
}
}
}
}
}
}
return ret / 3;
}
inline int NearestPoint(const vector<Real>& points, Real x, Real y, Real z)
{
Real pt[] = { x, y, z };
return NearestPoint(points, pt);
}
inline int NearestPoint(const vector<Real>& points, const Real* pt)
{
Real p[] = { pt[0], pt[1], pt[2] };
return NearestPoint(points, p);
}
Real GaussUnit(const vector<Real>& points)
{
Real range[6] = {
DBL_MAX, -DBL_MAX,
DBL_MAX, -DBL_MAX,
DBL_MAX, -DBL_MAX,
};
unsigned int i, ptsize = points.size() / 3;
for(i = 0; i < ptsize; i++)
{
const Real& x = points[i * 3 + 0];
const Real& y = points[i * 3 + 1];
const Real& z = points[i * 3 + 2];
if(x < range[0]) range[0] = x;
if(x > range[1]) range[1] = x;
if(y < range[2]) range[2] = y;
if(y > range[3]) range[3] = y;
if(z < range[4]) range[4] = z;
if(z > range[5]) range[5] = z;
}
return 2 * pow((range[1] - range[0]) * (range[3] - range[2]) * (range[5] - range[4]) / ptsize, 1/3.0);
}
inline void init(Real org[3], Real unit)
{
m_fOrg[0] = org[0]; m_fOrg[1] = org[1]; m_fOrg[2] = org[2];
m_fUnit = unit;
}
inline void init(const vector<Real>& points, Real org[3], Real unit)
{
m_fOrg[0] = org[0]; m_fOrg[1] = org[1]; m_fOrg[2] = org[2];
m_fUnit = unit;
tagIndex ind;
unsigned int size = points.size() / 3;
for(unsigned int i = 0; i < size; i++)
{
GetIndex(&(points[i * 3]), ind);
m_mapSortedPoints[ind].push_back(i);
}
}
inline void init(const vector<Real>& points)
{
m_fOrg[0] = points[0]; m_fOrg[1] = points[1]; m_fOrg[2] = points[2];
m_fUnit = GaussUnit(points);
tagIndex ind;
unsigned int size = points.size() / 3;
for(unsigned int i = 0; i < size; i++)
{
GetIndex(&(points[i * 3]), ind);
m_mapSortedPoints[ind].push_back(i);
}
}
inline void clear()
{
m_mapSortedPoints.clear();
}
CSortPoints(Real min_dist = 1.0e-6f) : m_fMinDist(min_dist)
{
}
~CSortPoints()
{
}
};
}
stl.cpp
inline float GetUnit(float x[3], float y[3], float z[3])
{
float ret[3];
ret[0] = fabs(x[0] - y[0]) > fabs(x[1] - y[1]) ? fabs(x[0] - y[0]) : fabs(x[1] - y[1]);
if (fabs(x[2] - y[2]) > ret[0]) ret[0] = fabs(x[2] - y[2]);
ret[1] = fabs(x[0] - z[0]) > fabs(x[1] - z[1]) ? fabs(x[0] - z[0]) : fabs(x[1] - z[1]);
if (fabs(x[2] - z[2]) > ret[1]) ret[1] = fabs(x[2] - z[2]);
ret[2] = fabs(z[0] - y[0]) > fabs(z[1] - y[1]) ? fabs(z[0] - y[0]) : fabs(z[1] - y[1]);
if (fabs(z[2] - y[2]) > ret[2]) ret[2] = fabs(z[2] - y[2]);
if (ret[0] > ret[1]) ret[0] = ret[1];
if (ret[0] > ret[2]) ret[0] = ret[2];
return ret[0];
}
inline bool ReadSTL(const wchar_t* wszPath, vector<float>& points, vector<float>& normals, vector<__int32>& triangles)
{
ifstream infile(wszPath);
if (!infile)
return false;
float org[3], unit;
float n[3]; float x[3]; float y[3]; float z[3];
char unusered[2];
int ix, iy, iz;
SortPoint::CSortPoints<float> sorted_points;
char string[256] = "";
infile >> string; //read "solid"
if (_strnicmp(string, "solid", 5) != 0) // 二进制
{
infile.close();
FileStream fStream;
if (!fStream.OpenFile(wszPath))
return false;
char info[90];
int size;
fStream.Read(info, sizeof(char) * 80);
fStream.Read(&size, sizeof(int));
for (int i = 0; i < size; i++)
{
fStream.Read(n, sizeof(float) * 3);
fStream.Read(x, sizeof(float) * 3);
fStream.Read(y, sizeof(float) * 3);
fStream.Read(z, sizeof(float) * 3);
fStream.Read(unusered, sizeof(char) * 2);
if (points.size() == 0)
{
unit = GetUnit(x, y, z);
org[0] = x[0]; org[1] = x[1]; org[2] = x[2];
sorted_points.init(org, unit);
}
normals.push_back(n[0]); normals.push_back(n[1]); normals.push_back(n[2]);
ix = sorted_points.insert_point(x, points);
iy = sorted_points.insert_point(y, points);
iz = sorted_points.insert_point(z, points);
if (ix != iy && iy != iz && ix != iz)
triangles.push_back(ix); triangles.push_back(iy); triangles.push_back(iz);
}
return true;
}
else // 文本
{
while (_strnicmp(string, "facet", 5) != 0) // 读到facet为止
infile >> string;
do
{
infile >> string; //read "normal"
infile >> n[0] >> n[1] >> n[2];
infile >> string; //read "outer"
infile >> string; //read "loop"
infile >> string; //read "vertex"
infile >> x[0] >> x[1] >> x[2];
infile >> string; //read "vertex"
infile >> y[0] >> y[1] >> y[2];
infile >> string; //read "vertex"
infile >> z[0] >> z[1] >> z[2];
if (points.size() == 0)
{
unit = GetUnit(x, y, z);
org[0] = x[0]; org[1] = x[1]; org[2] = x[2];
sorted_points.init(org, unit);
}
normals.push_back(n[0]); normals.push_back(n[1]); normals.push_back(n[2]);
ix = sorted_points.insert_point(x, points);
iy = sorted_points.insert_point(y, points);
iz = sorted_points.insert_point(z, points);
triangles.push_back(ix); triangles.push_back(iy); triangles.push_back(iz);
infile >> string; // read "endloop"
infile >> string; // read "endfacet"
infile >> string; // read "facet" or "endsolid"
if (_strnicmp(string, "endsolid", 8) == 0)
{
infile >> string;
if (_strnicmp(string, "solid", 8) == 0)
infile >> string;
else
break;
}
} while (_strnicmp(string, "facet", 5) == 0);
infile.close();
return true;
}
return false;
}
inline bool WriteSTL(const wchar_t* wszPath, vector<float>& points, bool bBinary)
{
if (!bBinary)
{
ofstream file(wszPath);
if (!file)
return false;
file << "Solid" << endl;
for (size_t i = 0; i < points.size(); i += 12)
{
file << " Facet Normal " << points[i + 0] << " " << points[i + 1] << " " << points[i + 2] << endl;
file << " Outer Loop" << endl;
file << " Vertex " << points[i + 3] << " " << points[i + 4] << " " << points[i + 5] << endl;
file << " Vertex " << points[i + 6] << " " << points[i + 7] << " " << points[i + 8] << endl;
file << " Vertex " << points[i + 9] << " " << points[i + 10] << " " << points[i + 11] << endl;
file << " Endloop" << endl;
file << " Endfacet" << endl;
}
file << "Endsolid" << endl;
file.close();
}
else
{
//iostream fStream;
FileStream fStream;
if (!fStream.CreateFile(wszPath))
return false;
char info[90];
int size = points.size() / 12;
fStream.Write(info, sizeof(char) * 80);
fStream.Write(&size, sizeof(int));
for (int i = 0; i < size; i++)
{
fStream.Write(&(points[i * 12]), sizeof(float) * 12);
char reserved[2];
fStream.Write(reserved, sizeof(char) * 2);
}
}
return true;
}