Show toolbar

2013年7月18日 星期四

Read STL Model file and export graphics using GD Library

標題:讀取STL模型檔案並使用GD Library匯出圖形
VC++ (main.cpp):
#include "stdafx.h"
#include <iostream>
#include <regex>
#include <fstream>
#include "gd/gd.h"
#include "gd/gdfontg.h"
#include "gd/gdfontt.h"
#include "gd/gdfonts.h"
#include "gd/gdfontmb.h"
#include "gd/gdfontl.h"
#pragma comment(lib, "lib/bgd.lib")
using namespace std;

class pos
{
public:
    float x;
    float y;
    float z;
};

class ERR
{
private:
    int kind;
public:
    ERR(int k) : kind(k){}; //建構函式
    char* message()
    {
        switch(kind)
        {
        case 0:
            return "Parameter Error!";
        case 1:
            return "Path Error!";
        case 2:
            return "File Error!";
        case 3:
            return "Array Size is too small.";
        case 4:
            return "STL Format Error!";
        }
    }
};

void draw(gdImagePtr im, pos vArr[], int v, int color)
{
    int i = 0;
    for(i=0;i<v;i+=3)
    {
        gdImageLine(im, (int)vArr[i].x, (int)vArr[i].y, (int)vArr[i+1].x, (int)vArr[i+1].y, color);
        gdImageLine(im, (int)vArr[i+1].x, (int)vArr[i+1].y, (int)vArr[i+2].x, (int)vArr[i+2].y, color);
        gdImageLine(im, (int)vArr[i].x, (int)vArr[i].y, (int)vArr[i+2].x, (int)vArr[i+2].y, color);
    }
}

int main(int argc, char* argv[])
{
    const float zoom = 5;
    const int arrSize = 3000;
    const int width = 500;
    const int height = 500;
    int i = 0, normals = 0, vertexs = 0;
    char pathChar[1024];
    char stlName[1024];
    string lines = "";

    pos *normalArr;
    pos *vertexArr;

    regex pathRegex("([a-zA-Z]\:\\\\(?:[^\\\\]+\\\\)*)(.*)"); //"C:\\temp\\hello.txt"
    regex solid(" *solid.*");
    regex facetNormal(" *facet normal ([+-]?(?=\.[0-9]|[0-9])(?:[0-9]+)?(?:\.?[0-9]*)(?:[eE][+-]?[0-9]+)?) ([+-]?(?=\.[0-9]|[0-9])(?:[0-9]+)?(?:\.?[0-9]*)(?:[eE][+-]?[0-9]+)?) ([+-]?(?=\.[0-9]|[0-9])(?:[0-9]+)?(?:\.?[0-9]*)(?:[eE][+-]?[0-9]+)?)");
    regex outerLoop(" *outer loop");
    regex vertex(" *vertex ([+-]?(?=\.[0-9]|[0-9])(?:[0-9]+)?(?:\.?[0-9]*)(?:[eE][+-]?[0-9]+)?) ([+-]?(?=\.[0-9]|[0-9])(?:[0-9]+)?(?:\.?[0-9]*)(?:[eE][+-]?[0-9]+)?) ([+-]?(?=\.[0-9]|[0-9])(?:[0-9]+)?(?:\.?[0-9]*)(?:[eE][+-]?[0-9]+)?)");
    regex endLoop(" *endloop");
    regex endfacet(" *endfacet");
    regex endsolid(" *endsolid");
    
    cmatch pathMatch;
    smatch normalMatch;
    smatch vertexMatch;

    try
    {
        if(argc<2) throw ERR(1); //Check Parameter

        strcpy(pathChar, argv[1]); //Get STL Path
        if(!regex_match(pathChar, pathMatch, pathRegex)) throw ERR(1); //Check STL Path

        strcpy(stlName, pathMatch[2].str().c_str()); //Get STL Name

        ifstream File(pathChar);
        if (!File.is_open()) throw ERR(2); //Check File

        normalArr = new pos[arrSize]; //宣告Facet normal動態陣列大小
        vertexArr = new pos[arrSize*3]; //宣告Vertex動態陣列大小

        cout << "Reading Now..." << endl;

        //solid
        if(!File.good())  throw ERR(4);
        getline(File, lines);
        if(!regex_match(lines, solid)) throw ERR(4);

        while(File.good())
        {
            if(normals >= arrSize) throw ERR(3); //Check Array Size

            //facet normal
            getline(File, lines);
            if(regex_match(lines, normalMatch, facetNormal))
            {
                normalArr[normals].x = atof(normalMatch[1].str().c_str()) + width/2;
                normalArr[normals].y = atof(normalMatch[2].str().c_str()) + height/2;
                normalArr[normals].z = atof(normalMatch[3].str().c_str());
                normals++;
            }
            else if(regex_match(lines, endsolid)) //end solid
            {
                break;
            }
            else
            {
                throw ERR(4);
            }
 
            //outer loop
            getline(File, lines);
            if(!regex_match(lines, outerLoop)) throw ERR(4);
 
            //vertex
            for(i=0;i<3;i++)
            {
                getline(File, lines);
                if(regex_match(lines, vertexMatch, vertex))
                {
                    vertexArr[vertexs].x = atof(vertexMatch[1].str().c_str())*zoom + width/2;
                    vertexArr[vertexs].y = atof(vertexMatch[2].str().c_str())*zoom + height/2;
                    vertexArr[vertexs].z = atof(vertexMatch[3].str().c_str())*zoom;
                    vertexs++;
                }
                else
                {
                    throw ERR(4);
                }
            }
 
            //end loop
            getline(File, lines);
            if(!regex_match(lines, endLoop)) throw ERR(4);
 
            //end facet
            getline(File, lines);
            if(!regex_match(lines, endfacet)) throw ERR(4);
        }
        File.close();

        cout << "Facet Normal: " << normals << endl;
        cout << "Vertex: " << vertexs << endl;
        cout << "Done." << endl;

        // --- draw ---
        cout << "Drawing Now..." << endl;

        FILE *out;
        int size;
        char *data;
 
        gdImagePtr im = gdImageCreate(width, height);
     
        int white =  gdImageColorAllocate(im, 255, 255, 255), //Background
            black =  gdImageColorAllocate(im, 0, 0, 0),
            blue =   gdImageColorAllocate(im, 0, 0, 255),
            cyan =   gdImageColorAllocate(im, 0, 255, 255),
            green =  gdImageColorAllocate(im, 128, 255, 0),
            red =    gdImageColorAllocate(im, 255, 0, 0),
            purple = gdImageColorAllocate(im, 255, 0, 255),
            orange = gdImageColorAllocate(im, 255, 128, 0),
            yellow = gdImageColorAllocate(im, 255, 255, 0);
 
        strcpy(pathChar, argv[0]); //Get Execution Path
        if(!regex_match(pathChar, pathMatch, pathRegex)) throw ERR(1); //Check Execution Path
        strcpy(pathChar, pathMatch[1].str().c_str()); //Get Folder Path
        strcat(pathChar, stlName); //Connections Folder Path and STL Name
        strcat(pathChar, ".png"); //Connections Path and Extension

        out = fopen(pathChar, "wb");
        if (!out) throw ERR(1);

        draw(im, vertexArr, vertexs, black);

        data = (char *) gdImagePngPtr(im, &size);
        if (!data) throw ERR(2);

        if (fwrite(data, 1, size, out) != size) throw ERR(3);

        if (fclose(out) != 0) throw ERR(4);
        gdFree(data);
        cout << "Done." << endl;
    }
    catch(ERR e)
    {
        cout << e.message() << endl;
    }
    system("pause");

    return 0;
}

說明:
首先拖曳一個STL模型檔案至執行檔以進行讀取,一邊進行檔案比對一邊將點資料存入類別陣列內,再使用GD Library匯出png圖片檔。

沒有留言:

張貼留言