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; }