STL檔案序列化讀取

Augusdi發表於2014-03-11
//實體類
class CSTLSolid
{
public: 
	//constructor and destructor
	CSTLSolid()
	{
		m_bInitialized=FALSE;
		m_pIntersections=NULL;
	}
	~CSTLSolid(void)	{delete []m_pIntersections;}
	// Implementation
	void WriteArchive(CArchive& archive);
	int Initialize(const char* fileName);	//Succeed if return zero, else return -1.
	int CutSlice(double ,C2DContour&);
	void Find_Min_Max_Value(CSTLPoint&, int );
	// Attributes
	STLPointArray m_points;
	STLEdgeArray m_edges;
	STLFaceArray m_faces;
	BOOL m_bInitialized;						//當前實體是否已經初始化
	BOOL blReportFaceErr;						//模型出現錯誤是否報告[報告/忽略]
	STLIntersection* m_pIntersections;			//記錄切片所得到的交點
	double m_xMin ,m_xMax ,m_yMin ,m_yMax ,m_zMin ,m_zMax;
	double m_modeheight;
protected:
	// Implementation 
	void InitIntersections(void);				//初始化交點矩陣
public:
	// 重新計演算法向量<沒有錯誤返回0><返回錯誤數目>
	int ReCalNormal(void);
	void RemoveAll(void);
};
int CSTLSolid::Initialize(const char* fileName) 
{

    /*********************Begin initialization**********************
    ***************************************************************/

    LONG  fileSize=0;                //檔案大小
    ULONG totalFaces=0;              //總面數
    ULONG pointCounter=0;            //點計數器 
    ULONG edgeCounter=0;             //邊計數器 
    ULONG faceCounter=0;             //面計數器
    /**********************Read STL file****************************
    ***************************************************************/
    //Open as ASCII STL file

    ifstream inputFile(fileName, ios::in | ios::_Nocreate);
    if (inputFile.bad()) //損壞的檔案
    {
        globalErrorMessage.SetErrorMsg("損壞的檔案!");
        globalErrorMessage.ShowErrorMsg();
        inputFile.close();
        return -1;
    }
    inputFile.seekg(0,ios::end);

    if ( (fileSize=inputFile.tellg()) == -1L )//空檔案
    {
        globalErrorMessage.SetErrorMsg("空檔案錯誤!");
        globalErrorMessage.ShowErrorMsg();
        inputFile.close();
        return -1;
    }
    inputFile.seekg(0,ios::beg);
   ////////////////////////////////////////////////////////////////
    //Check if "inputFile" is an ASCII file
    //and search the occurrence of "facet".

    LONG filePtr;
    STLFILETYPE fileType=NONSTLFILE;
    
    if (IsASCIISTLFile(inputFile, filePtr))  //判斷檔案格式為ASCII檔案還是BINARY檔案
    {
        inputFile.seekg(filePtr, ios::beg); //Rewind file pointer to ''facet"
//         totalFaces=fileSize/250;            //總面片數 <不適用於多種軟體生成的ASCII檔案>
        fileType=ASCIISTLFILE;                //標記為ASCII檔案
    }
    else
    {
        inputFile.close();
        inputFile.open(fileName, ios::in | ios::_Nocreate | ios::binary);
        inputFile.seekg(80, ios::beg);

        if (inputFile.bad()) //不可讀檔案
        {
            globalErrorMessage.SetErrorMsg("Binary STL不可讀!");
            globalErrorMessage.ShowErrorMsg();
            inputFile.close();
            return -1;
        }

        //取得總面片數 
        inputFile.read(( char* )(&totalFaces), sizeof (totalFaces));

        if (inputFile.bad())
        {
            globalErrorMessage.SetErrorMsg("Binary STL不可讀!");
            globalErrorMessage.ShowErrorMsg();
            inputFile.close();
            return -1;
        }

        fileType=BINSTLFILE;
    }

    ////////////////////////////////////////////////////////////////
    //Read STL file . Note: "inputFile" has been seeked to 
    //"facet" and "totalFaces" has already been setted .
    
    CSTLPoint point;
    CSTLFace face;
    if (fileType==ASCIISTLFILE)
    {
        ////////////////////////////////////////////////////////////
        //Read ASCII STL File beginning at "facet" 讀取ASCII檔案
    
        char buff[25];

        //Set temporary array size
//         tempPointArray.SetSize(totalFaces*3); //因為改為面片計數。此處修改
//         m_faces.SetSize(totalFaces);
            
        while(1)
        {
            inputFile>>buff;

            //The file pointer reaches the "facet" or the file ends ?
            if (_strnicmp(buff, "facet", strlen("facet"))!=0)
                break;

            //Read normal vector 讀取法向量
            if(!ReadKeyword(inputFile,"normal"))
                return -1;

            point.ReadSTLFile(inputFile,fileType);
            face.m_vector_normal=point;

            //Read three Points
            if(!ReadKeyword(inputFile,"outer"))
                return -1;

            if(!ReadKeyword(inputFile,"loop"))
                return -1;

            for (INT i=0; i<3; i++)
            {
                if(!ReadKeyword(inputFile,"vertex"))
                    return -1;

                point.ReadSTLFile(inputFile,fileType);
                tempPointArray.Add(point);   //由SetAt改為Add
                face.m_points[i]=pointCounter;
                Find_Min_Max_Value(point,pointCounter);
                pointCounter++;
            }

            if(!ReadKeyword(inputFile,"endloop"))
                return -1;

            if(!ReadKeyword(inputFile,"endfacet"))
                return -1;

            m_faces.Add(face);
            faceCounter++; 
        }            
        totalFaces = faceCounter;
        ////////////////////////////////////////////////////////////
        //Verify the ASCII file ends with "endsolid".

        if (_strnicmp(buff, "endsolid", sizeof(buff))!=0)
        {
            globalErrorMessage.SetErrorMsg("endsolid錯誤!");
            globalErrorMessage.ShowErrorMsg();
            return -1;
        }
    }
    else
    {
        ////////////////////////////////////////////////////////////
        //Read BIN STL File 讀取二進位制檔案
        tempPointArray.SetSize(totalFaces*3);
        m_faces.SetSize(totalFaces);

        for (ULONG counter = 0; counter < totalFaces; counter++)
        {
            if (inputFile.eof()) //容錯處理
            {
                if (counter + 1 != totalFaces)
                {
                    globalErrorMessage.SetErrorMsg("實際讀取面片不符!");
                    globalErrorMessage.ShowErrorMsg();
                }
                totalFaces=counter; 
                break;
            };
                
            //Read normal vector 讀取法向量
            point.ReadSTLFile(inputFile,fileType);
            face.m_vector_normal=point;

            //Read three Points 讀取三個點
            for (INT i=0; i<3; i++)
            {
                point.ReadSTLFile(inputFile,fileType);
                tempPointArray.SetAt(pointCounter, point);
                face.m_points[i]=pointCounter;
                Find_Min_Max_Value(point,pointCounter);
                pointCounter++;
            }            
            m_faces.SetAt(faceCounter++, face);

            //Read attribute word (must be ZERO)
            WORD attribute;
            inputFile.read(( char* )(&attribute), sizeof(attribute));

            if (inputFile.bad())
            {
                globalErrorMessage.SetErrorMsg("STL檔案bad錯誤!");
                globalErrorMessage.ShowErrorMsg();
                inputFile.close();
                return -1;
            }
            
//             if (attribute != 0) //此規則不正確,面片備註不要求一定為零
//             {
//                 globalErrorMessage.SetErrorMsg("STL檔案attribute不為零!");
//                 globalErrorMessage.ShowErrorMsg();
//                 inputFile.close();
//                 return -1;
//             }
                    
        }
    }
    m_modeheight = m_zMax - m_zMin;
    //Close the input file
    inputFile.close();
    ////////////////////////////////////////////////////////////////
    //Set array size to the actual size

    tempPointArray.SetSize(pointCounter);
    m_faces.SetSize(faceCounter);
    /***********************排序 並 重新組織點***********************/

    ////////////////////////////////////////////////////////////////
    //1.點排序

    /************************建立STL邊資訊****************************/

    //2.邊排序

    //3.重組邊結構

     //4.重建 STL 邊 和 STL 面關係
 //5.Release memory allocation.

m_bInitialized=TRUE ;
    /******************      End        ***************************
    ***************************************************************/
    
    return 0;
}