丶不离不弃 发表于 2019-10-16 10:32:48

求解关于C++写ghostview画图程序的问题

本帖最后由 丶不离不弃 于 2019-10-16 10:36 编辑

我们老师布置了一个作业就是利用C++来写ghostview(或者adobe)的指令,生成一个test.ps文件来画各种图形,然后来填充颜色。填充颜色是setrgbcolor,分别画出一个填充红色的矩形,画一个边框为红色的矩形,
连续画6个填充红色的矩形,接着画一个绿色边框的圆,直线,和6边形。里面的数据分别是起始点x,y,宽,高。polygon中时外接圆圆心的左边,外接圆半径以及边的数目。
然后我遇到个问题就是,我这个程序setrgbcolor只是在最开始出现2个语句,并不是在画每个图形的时候都出现,这导致绿色把红色都覆盖了,请问哪位大神能帮我把程序改改?谢谢!!
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
const double PI=3.141592653;
using namespace std;

class Shape{
private:
    double r, g, b;
    ofstream f;
public:
    void setrgb(double r, double g, double b){
      f<<r<<' '<<g<<' '<<b<<" setrgbcolor "<<endl;
    }
    virtual void draw(ostream& s) = 0;
};

class Circle:public Shape{
private:
    double x,y,radius;
public:
    Circle(double x, double y, double radius):x(x),y(y),radius(radius){}
    void draw(ostream& f){
      f<<x<<' '<<y<<' '<<radius<<" 0 360 arc stroke"<<endl;
    }
};

class Line:public Shape{
private:
    double x1, x2,y1, y2;
public:
    Line(double x1, double y1,double x2, double y2):x1(x1),y1(y1),x2(x2),y2(y2){}
    void draw(ostream& f){
      f<<x1<<' '<<y1<<" moveto "<<'\n'<<x2<<' '<<y2<<" lineto"<<'\n'<< "stroke " <<endl;
    }
};

class Rect:public Shape{
private:
    double x, y, width, height;
public:
    Rect(double x, double y, double width, double height):x(x),y(y),width(width),height(height){}
    void draw(ostream& f){
      f<<x<<' '<<y<<" moveto "<<'\n'<<x+width<<' '<<y<<" lineto "<<'\n'<<x+width
         <<' '<<y+height<<" lineto "<<'\n'<<x<<' '<<y+height<<" lineto"<<'\n'<< "closepath stroke"<<endl;
    }
};
class Polygon:public Shape{
private:
    double x, y, radius,side;
public:
    Polygon(double x, double y, double radius, double side):x(x),y(y),radius(radius),side(side){}
    void draw(ostream& f){
      f<<x+radius<<' '<<y<<" moveto "<<endl;
      for(int i=1; i<side; i++){
            f<<x+radius*cos(2*i*PI/side)<<' '<<y+radius*sin(PI*2*i/side)<<" lineto "<<'\n';
      }
      f<<"closepath stroke"<<endl;

    }

};

class FilledRect:public Shape{
private:
    double x, y, width,height ;
public:
    FilledRect(double x, double y, double width, double height)
            :x(x),y(y),width(width),height(height){}
    void draw(ostream& f){
      f <<x << ' ' << y << " moveto " <<'\n'<< x+width
          << ' ' << y<< " lineto " <<'\n'<< x + width << ' ' << y + height
          << " lineto " <<'\n'<< x<< ' ' << y +height << " lineto"<<'\n'<< "closepath fill"<<endl;

    }
};

class FilledCircle:public Shape{
private:
    double x, y, radius;
public:
    FilledCircle(double x, double y, double radius):x(x),y(y),radius(radius){}
    void draw(ostream& f){
      f<<x<<' '<<y<<' '<<radius
         <<" 0 360 arc fill"<<endl;
    }
};

class Drawing {
private:
    ofstream f;
    vector<Shape*> shapes;
    int r, g, b;
public:
    void setrgb(double r, double g, double b){
      f<<r<<' '<<g<<' '<<b<<" setrgbcolor "<<endl;
    }
    Drawing(string filename) : f(filename.c_str()), shapes() {
    }
    void add( Shape* s ) {
      shapes.push_back(s);
    }
    void draw() {
      for (int i = 0; i <shapes.size(); i++)
            shapes->draw(f);
    }

};
int main() {
    ofstream f();
    Drawing d("../test2.txt");
    d.setrgb(1,0,0); // set drawing color to be bright red:1 0 0 setrgbcolor
    d.add(new FilledRect(100.0, 150.0, 200.0, 50)); // x y moveto x y lineto ... fill
    d.add(new Rect(100.0, 150.0, 200.0, 50));       // x y moveto x y lineto ... stroke
    for (int x = 0; x < 600; x += 100)
      d.add(new FilledCircle(x,200,50.0)); // x y r 0 360 arc fill
    d.setrgb(0,1,0); // the rest are green
    d.add(new Circle(0,0, 100)); // 0 0 100 0 360 stroke
    d.add(new Line(400,500, 600,550));
    d.add(new Polygon(200,200, 50, 6));
    d.draw();

}

superbe 发表于 2019-10-16 20:45:17

本帖最后由 superbe 于 2019-10-16 20:57 编辑

main里面只在最后d.draw()的时候才会输出全部图形,第一个和第二个d.setrgb之间的图形并没有输出,所以等于连续向文件中输出了两个setrgb,这样只是第二个setrgb才会对后面的图形起作用。

你可以在class Drawing里增加一个函数,用来清空shapes。
void clear(){
    shapes.clear();
}
在输出前几个红色的图形后,调用clear清空shapes,然后设置绿色再输出后面几个绿色图形。

main函数修改如下,为了图形不重叠,我调整了图形坐标(注释未改),根据实际情况修改吧:
int main() {
    //ofstream f();
    Drawing d("../test2.txt");
    d.setrgb(1, 0, 0); // set drawing color to be bright red:1 0 0 setrgbcolor
    d.add(new FilledRect(100.0, 150.0, 200.0, 50)); // x y moveto x y lineto ... fill
    d.add(new Rect(100.0, 250.0, 200.0, 50));       // x y moveto x y lineto ... stroke
    for (int x = 50; x < 650; x += 100)
      d.add(new FilledCircle(x, 400, 50.0)); // x y r 0 360 arc fill
    d.draw();//增加的行
    d.clear();//增加的行
    d.setrgb(0, 1, 0); // the rest are green
    d.add(new Circle(400, 100, 100)); // 0 0 100 0 360 stroke
    d.add(new Line(400, 500, 550, 550));
    d.add(new Polygon(200, 500, 50, 6));
    d.draw();
    return 0;
}

最后的效果是这样的:


生成的ps文件内容如下:

丶不离不弃 发表于 2019-10-16 22:02:47

superbe 发表于 2019-10-16 20:45
main里面只在最后d.draw()的时候才会输出全部图形,第一个和第二个d.setrgb之间的图形并没有输出,所以等于 ...

我们的main函数是老师先写好的,老师说不可以改,请问你可以说一下不改main函数只在class中编辑的解决方法嘛?谢谢!

superbe 发表于 2019-10-16 23:49:42

本帖最后由 superbe 于 2019-10-17 00:05 编辑

重新修改过了,试试可以吗

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
const double PI=3.141592653;
using namespace std;

class Shape{
private:
    double r, g, b;
    //ofstream f;
public:
    void setrgb(double r, double g, double b){//修改的函数
      //f<<r<<' '<<g<<' '<<b<<" setrgbcolor "<<endl;
      this->r = r;
      this->g = g;
      this->b = b;
    }
    void writergb(ostream& f){//增加的函数
      f<<r<<' '<<g<<' '<<b<<" setrgbcolor "<<endl;
    }
    virtual void draw(ostream& s) = 0;
};

class Circle:public Shape{
private:
    double x,y,radius;
public:
    Circle(double x, double y, double radius):x(x),y(y),radius(radius){}
    void draw(ostream& f){
      f<< x << ' ' << y <<' '<< radius <<" 0 360 arc stroke"<< endl;
    }
};

class Line:public Shape{
private:
    double x1, x2,y1, y2;
public:
    Line(double x1, double y1,double x2, double y2):x1(x1),y1(y1),x2(x2),y2(y2){}
    void draw(ostream& f){
      f<<x1<<' '<<y1<<" moveto "<<'\n'<<x2<<' '<<y2<<" lineto"<<'\n'<<"stroke "<<endl;
    }
};

class Rect:public Shape{
private:
    double x, y, width, height;
public:
    Rect(double x, double y, double width, double height):x(x),y(y),width(width),height(height){}
    void draw(ostream& f){
      f<<x<<' '<<y<<" moveto "<<'\n'<<x+width<<' '<<y<<" lineto "<<'\n'<<x+width
         <<' '<<y+height<<" lineto "<<'\n'<<x<<' '<<y+height<<" lineto"<<'\n'<< "closepath stroke"<<endl;
    }
};

class Polygon:public Shape{
private:
    double x, y, radius,side;
public:
    Polygon(double x, double y, double radius, double side):x(x),y(y),radius(radius),side(side){}
    void draw(ostream& f){
      f<<x+radius<<' '<<y<<" moveto "<<endl;
      for(int i=1; i<side; i++){
            f<<x+radius*cos(2*i*PI/side)<<' '<<y+radius*sin(PI*2*i/side)<<" lineto "<<'\n';
      }
      f<<"closepath stroke"<<endl;
    }
};

class FilledRect:public Shape{
private:
    double x, y, width,height ;
public:
    FilledRect(double x, double y, double width, double height)
            :x(x),y(y),width(width),height(height){}
    void draw(ostream& f){
      f <<x << ' ' << y << " moveto " <<'\n'<< x+width
          << ' ' << y<< " lineto " <<'\n'<< x + width << ' ' << y + height
          << " lineto " <<'\n'<< x<< ' ' << y +height << " lineto"<<'\n'<< "closepath fill"<<endl;

    }
};

class FilledCircle:public Shape{
private:
    double x, y, radius;
public:
    FilledCircle(double x, double y, double radius):x(x),y(y),radius(radius){}
    void draw(ostream& f){
      f<<x<<' '<<y<<' '<<radius<<" 0 360 arc fill"<<endl;
    }
};

class Drawing {
private:
    ofstream f;
    vector<Shape*> shapes;
    double r, g, b;
public:
    void setrgb(double r, double g, double b){//修改的函数
      //f<<r<<' '<<g<<' '<<b<<" setrgbcolor "<<endl;
      this->r = r;
      this->g = g;
      this->b = b;
    }
    Drawing(string filename) : f(filename.c_str()), shapes() {
    }
    void add( Shape *s ) {//修改的函数
      s->setrgb(r, g, b);
      shapes.push_back(s);
    }
    void draw() {    //修改的函数
      for (int i = 0; i <shapes.size(); i++){
            shapes->writergb(f);
            shapes->draw(f);
      }
    }
};

int main() {   //main未改动
    ofstream f();
    Drawing d("../test2.txt");
    d.setrgb(1,0,0); // set drawing color to be bright red:1 0 0 setrgbcolor
    d.add(new FilledRect(100.0, 150.0, 200.0, 50)); // x y moveto x y lineto ... fill
    d.add(new Rect(100.0, 150.0, 200.0, 50));       // x y moveto x y lineto ... stroke
    for (int x = 0; x < 600; x += 100)
      d.add(new FilledCircle(x,200,50.0)); // x y r 0 360 arc fill
    d.setrgb(0,1,0); // the rest are green
    d.add(new Circle(0,0, 100)); // 0 0 100 0 360 stroke
    d.add(new Line(400,500, 600,550));
    d.add(new Polygon(200,200, 50, 6));
    d.draw();

}

superbe 发表于 2019-10-17 00:13:27

解决思路是这样的:
调用d.setrgb时把rgb值存储在d中,以后添加每个图形时把rgb值设置到图形中。
最后输出时,先调用图形的writergb将其rgb值写到文件,接着再调用该图形的draw方法写入画图的命令。

丶不离不弃 发表于 2019-10-17 02:50:52

superbe 发表于 2019-10-17 00:13
解决思路是这样的:
调用d.setrgb时把rgb值存储在d中,以后添加每个图形时把rgb值设置到图形中。
最后输 ...

奥,我明白啦,谢谢你,你真厉害哇~~!我要是有你学的这么好就好了-。-
页: [1]
查看完整版本: 求解关于C++写ghostview画图程序的问题