2014-10-10 21 views
0

我想使用OpenGL绘制线条,圆形(最终可能是多边形,尽管我的解析器可以轻松扩展到这一端)。我的输入文件如下所示:如何使用重复格式存储整数数据?

L 0,0,175,55 
L 22, 8, 75, 100 
C 150, 200, 0 
L 99, -50, 217, 77 
Z 

etc. 

其中Z表示文件的结尾,C/L分别表示圆和线数据。由于一些早期的堆栈溢出的帮助和努力一点,我已经能够从我的输入解析整数数据.txt文件像这样(包含在.cpp文件本身的其他地方所有必要的库):

void parseFile() 
{ 
ifstream lines; 
lines.open("C:/Users/Me/Desktop/lines.txt"); //Adjust to proper absolute path of test file 
string currentLine; 

while(getline(lines, currentLine)) 
{ 

    if(currentLine.empty()) //Check that there is no garbage data in the parser 
     continue; 

    istringstream iss(currentLine); //Convert line of data into input stream 

    char type; // L, C or Z 

    if(!(iss >> type)) 
     continue; 

    switch(type) 
    { 
     case 'L': //If L, store as line (x0, y0, x1, y1) 
     { 
      char comma; 
      int x0, y0, x1, y1; 

      if(!(iss >> x0 >> comma >> y0 >> comma >> x1 >> comma >> y1)) 
      { 

       cerr << "ERROR: Failed to read L: " << currentLine << endl; 
       continue; 
      } 

      //STORE 
      cout << "(" << x0 << ", " << y0 << ", " << x1 << ", " << y1 << ")" << '\n'; 

      break; 
     } 
     case 'C': //If C, store as circle data (center x, center y, int radius) 
     { 
      char comma; 

      int xc, yc, rad; 

      if(!(iss >> xc >> comma >> yc >> comma >> rad)) 
      { 

       cerr << "ERROR: Failed to read C: " << currentLine << endl; 
       continue; 
      } 

      break; 
     } 
     case 'Z': //If Z, end the parsing 
     { 
      break; 
     } 
     default: 
      cerr << "ERROR: BAD INPUT " << currentLine << endl; 
    } 
} 
} 

我的困难是,虽然我知道每一行输入的格式,但它是正确的,我不知道会有多少行,或者结构是LCLC,LLLL还是你有什么。直线坐标将总是按照上面的四个一组进行解析,而圆将始终以三个为一组进行解析。因此,我想存储点,所以稍后我可以使用OpenGL函数来操作/绘制它们。我不知道如何做到这一点。我认为使用任意大的数组并且以4/3的集合读取它似乎是一个不好的解决方案,尤其是因为我不知道连续出现两个圆或线是否会出现,或者是否会跟随其他,给我留下不匹配的数据。一个向量可能更合适,因为它会有一个动态调整的大小,但我不知道如何有效地从向量中拉出数字,以确保我总是绘制正确的基元。

任何援助/指向正确的方向将不胜感激!

+0

节省内存很重要吗?或者是更重要的可读代码? – Winestone 2014-10-10 11:57:50

+0

当然,我重视内存使用的可读代码。数据输入只是整数值,一个大文件可能只包含几百个。 – 2014-10-10 12:06:27

回答

0

这是否适合您?

该代码有点麻烦,但你应该能够清理它,我希望你能明白它。不知道这是否是一个好的实现,但它似乎可以使用。

见结果,并在测试:http://ideone.com/cr1GL9 一类将所有的东西,并使其取消分配上解构:http://ideone.com/2Hyhqg

下面的代码输出:

LINE: 11 12 13 14 
LINE: 21 22 23 24 
CIRCLE: 31 32 33 
LINE: 41 42 43 44 
CIRCLE: 51 52 53 
POLYGON: [0]{11, 12} [1]{21, 22} [2]{31, 32} [3]{41, 42} [4]{51, 52} 

代码:

//For testing 
#include <iostream> 

//Required to use vector 
#include <vector> 

//Base class for things to push on 
class drawingObject { }; 

//Holds data for a circle 
class drawingCircle : drawingObject { 
    public: 
     drawingCircle (int _xc, int _yc, int _rad) { 
      xc = _xc; 
      yc = _yc; 
      rad = _rad; 
     } 

     int xc, yc, rad; 
}; 

//Holds data for a line 
class drawingLine : drawingObject { 
    public: 
     drawingLine (int _x0, int _y0, int _x1, int _y1) { 
      x0 = _x0; 
      y0 = _y0; 
      x1 = _x1; 
      y1 = _y1; 
     } 

     int x0, y0, x1, y1; 
}; 

//Holds data for a polygon 
class drawingPolygon : drawingObject { 
    public: 
     class Point { 
      public: 
       Point() {} 
       Point (int _x, int _y) { 
        x = _x; 
        y = _y; 
       } 
       int x, y; 
     }; 

     drawingPolygon (std::vector<drawingPolygon::Point>& points) { 
      point = points; 
     } 

     std::vector<drawingPolygon::Point> point; 
}; 

//Holds any type of item to draw 
class drawingData { 
    public: 
     //So you can tell if it's a circle or line 
     enum Type { 
      LINE, 
      CIRCLE, 
      POLYGON 
     }; 

     drawingData (Type _type, drawingObject* _data) { 
      type = _type; 
      data = _data; 
     } 

     Type type; 
     drawingObject* data; 
}; 

//Pushing on some object 
void pushObject (std::vector<drawingData*>& vec, drawingData::Type type, drawingObject* obj) { 
    vec.push_back(new drawingData(type, obj)); 
} 

//Pushing on a line 
void pushLine (std::vector<drawingData*>& vec, int x0, int y0, int x1, int y1) { 
    pushObject(vec, drawingData::Type::LINE, 
     reinterpret_cast<drawingObject*> (new drawingLine(x0, y0, x1, y1)) 
    ); 
} 

//Pushing on a circle 
void pushCircle (std::vector<drawingData*>& vec, int xc, int yc, int rad) { 
    pushObject(vec, drawingData::Type::CIRCLE, 
     reinterpret_cast<drawingObject*> (new drawingCircle(xc, yc, rad)) 
    ); 
} 

//Pusing on a polygon 
void pushPolygon (std::vector<drawingData*>& vec, std::vector<drawingPolygon::Point>& points) { 
    pushObject(vec, drawingData::Type::POLYGON, 
     reinterpret_cast<drawingObject*> (new drawingPolygon(points)) 
    ); 
} 

int main() { 

    //Vector that holds drawingData pointers 
    std::vector<drawingData*> myvector; 

    //Pushing on some stuff 
    pushLine (myvector, 11, 12, 13, 14); 
    pushLine (myvector, 21, 22, 23, 24); 
    pushCircle (myvector, 31, 32, 33); 
    pushLine (myvector, 41, 42, 43, 44); 
    pushCircle (myvector, 51, 52, 53); 

    std::vector<drawingPolygon::Point> points; 
    points.push_back(drawingPolygon::Point(11, 12)); 
    points.push_back(drawingPolygon::Point(21, 22)); 
    points.push_back(drawingPolygon::Point(31, 32)); 
    points.push_back(drawingPolygon::Point(41, 42)); 
    points.push_back(drawingPolygon::Point(51, 52)); 
    pushPolygon(myvector, points); 

    //Save some space 
    myvector.resize(myvector.size()); 

    //Loop through each element 
    for (unsigned int i = 0;i < myvector.size();++i) { 
     switch (myvector[i]->type) { 
      case drawingData::Type::LINE: { 
       //Make it easier to access the line data 
       drawingLine* currLine = reinterpret_cast<drawingLine*>(myvector[i]->data); 

       //Accessing elements 
       std::cout << "LINE: " << 
        currLine->x0 << " " << currLine->y0 << " " << 
        currLine->x1 << " " << currLine->y1 << std::endl; 

       break; 
      } 

      case drawingData::Type::CIRCLE: { 
       //Make it easier to access the circle data 
       drawingCircle* currCircle = reinterpret_cast<drawingCircle*>(myvector[i]->data); 

       //Accessing elements 
       std::cout << "CIRCLE: " << 
        currCircle->xc << " " << currCircle->yc << " " << currCircle->rad << std::endl; 

       break; 
      } 

      case drawingData::Type::POLYGON: { 
       //Make it easier to access the polygon data 
       drawingPolygon* currPolygon = reinterpret_cast<drawingPolygon*>(myvector[i]->data); 

       //Accessing elements 
       std::cout << "POLYGON: "; 
       for (unsigned int i = 0;i < currPolygon->point.size();++i) { 
        std::cout << "[" << i << "]" << "{" << currPolygon->point[i].x << ", " << currPolygon->point[i].y << "} "; 
       } 
       std::cout << std::endl; 

       break; 
      } 
     } 
    } 

    return 0; 
} 

另外不要忘了deletenew'ed!否则,你会得到讨厌的内存泄漏。你可以写一个drawingData的解构器来解决这个问题。问我,如果你不明白,事实上,如果你不明白/想解释什么,请问我。 :)