2)编写一个表示画布的类Canvas,所有图形由该类维护,Canvas类有一个方法是保存绘图结果到一个bmp文件。保存bmp文件的代码在BmpIO.h和BmpIO.cpp中。Canvas类另一个方法是添加基本图形实例到画布中。其它方法根据需要自行添加。
shape.h
#ifndef _SHAPE_H_
#define _SHAPE_H_
#include <vector>
using namespace std;
namespace Graphics {
class Point {
public:
int x, y;
public:
Point() :x(0), y(0) {}
Point(int _x, int _y) :x(_x), y(_y) {}
double DistanceTo(const Point p);
};
class Color {
public:
unsigned char r, g, b;
static Color red, green, blue, white, black;
public:
Color() :r(0xFF), g(0xFF), b(0xFF) {}
Color(unsigned char _r, unsigned char _g, unsigned char _b) :
r(_r), g(_g), b(_b) {}
Color(const Color &clr) :r(clr.r), g(clr.g), b(clr.b) {}
friend bool operator==(const Color &c1, const Color &c2);
};
class Shape {
private:
Color lineColor;
public:
Shape() :lineColor(Color::black) {}
Shape(const Color _lineColor) : lineColor(_lineColor) {}
Shape(const Shape &s) :lineColor(s.lineColor) {}
void setLineColor(const Color _lineColor) { lineColor = _lineColor; };
Color getLineColor() const { return lineColor; }
virtual void GetEdgePointList(vector<Point> &ptList) = 0;
virtual Shape* Clone() const = 0;
virtual ~Shape() {};
};
class Rect :public Shape {
private:
Point p;
int width, height;
public:
Rect() :p(Point()), width(1), height(1) {}
Rect(const Point &position, const int _width, const int _height) :
p(position), width(_width), height(_height) {}
Rect(const Color _lineColor, const Point &position,
const int _width, const int _height) :
Shape(_lineColor), p(position), width(_width), height(_height) {}
Rect(const Rect &r) :Shape(r), p(r.p), width(r.width), height(r.height) {}
Rect& operator=(const Rect &r);
Shape* Clone() const;
void GetEdgePointList(vector<Point> &ptList);
~Rect() {}
};
class Circle :public Shape {//声明Circle类
private:
Point p;//圆心p点
int r;//半径r
public:
Circle() :p(Point()), r(1) {}//默认构造函数
Circle(const Point &position, const int _r) :p(position), r(_r) {}//带参构造函数
Circle(const Color _lineColor, const Point &position, const int _r) :
Shape(_lineColor), p(position), r(_r) {}
Circle(const Circle&c) :Shape(c), p(c.p), r(c.r) {}//拷贝构造函数
Circle&operator=(const Circle &c);//拷贝赋值函数
Shape*Clone()const;
void GetEdgePointList(vector<Point> &ptList);
};
class Ellipse :public Shape {//声明椭圆类
public:
Point p;//椭圆中心点
int a, b;//椭圆的半长轴与半短轴
private:
Ellipse() :p(Point()), a(2), b(1) {}//无参构造函数,将a、b分别初始化为2、1
Ellipse(const Point &position, const int _a, const int _b) :p(position), a(_a), b(_b) {}
Ellipse(const Color _lineColor, const Point &position, const int _a, const int _b) :
Shape(_lineColor), p(position), a(_a), b(_b) {}//带参构造函数
Ellipse(const Ellipse&o) :Shape(o), p(o.p), a(o.a), b(o.b) {}//拷贝构造函数
Ellipse&operator=(const Ellipse &o);//拷贝赋值函数
Shape*Clone()const;
void GetEdgePointList(vector<Point> &ptList);
};
}
#endif
shape.cpp
#include "Shape.h"
using namespace Graphics;
Color Color::red(0xFF, 0x00, 0x00);
Color Color::green(0x00, 0xFF, 0x00);
Color Color::blue(0x00, 0x00, 0xFF);
Color Color::white(0xFF, 0xFF, 0xFF);
Color Color::black(0x00, 0x00, 0x00);
bool Graphics::operator==(const Color &c1, const Color &c2) {//加上了Graphics
return (c1.r == c2.r) && (c1.g == c2.g) && (c1.b == c2.b);
}
double Point::DistanceTo(const Point p) {
return sqrt((p.x - x)*(p.x - x) + (p.y - y)*(p.y - y));
}
Rect& Rect::operator=(const Rect &r) {
if (this != &r) {
setLineColor(r.getLineColor());
p = r.p;
width = r.width;
height = r.height;
}
return *this;
}
Shape* Rect::Clone() const {
return new Rect(*this);
}
void Rect::GetEdgePointList(vector<Point> &ptList) {
ptList.clear();
for (int i = p.x; i < p.x + width; ++i) {
ptList.push_back(Point(i, p.y));
ptList.push_back(Point(i, p.y + height));
}
for (int j = p.y; j < p.y + height; ++j) {
ptList.push_back(Point(p.x, j));
ptList.push_back(Point(p.x + width, j));
}
}
Circle& Circle::operator=(const Circle &c) {
if (this != &c) {
setLineColor(c.getLineColor());
p = c.p;
r = c.r;
}
return *this;
}
Shape* Circle::Clone() const { return new Circle(*this); }
void Circle::GetEdgePointList(vector<Point> &ptList) {
ptList.clear();
if (r <= 0)return;
double delta = std::fmax(1 / r, 1e-5);
static const double two_pi = 3.1415926 * 2;
for (double t = 0; t < two_pi; t += delta) {
int x = static_cast<int>(r*cos(t) + p.x);
int y = static_cast<int>(r*sin(t) + p.y);
ptList.push_back(Point(x, y));
}
}
Ellipse&Ellipse::operator=(const Ellipse &o) {
if (this != &o) {
setLineColor(o.getLineColor());
p = o.p;
a = o.a;
b = o.b;
}
return *this;
}
Shape* Ellipse::Clone() const { return new Ellipse(*this); }
void Ellipse::GetEdgePointList(vector<Point> &ptList) {
ptList.clear();
if (a <= 0 || b <= 0)return;
double delta = std::fmax(1 / (a), 1e-5);
static const double two_pi = 3.1415926 * 2;
for (double t = 0; t < two_pi; t += delta) {
int x = static_cast<int>(a*cos(t) + p.x);
int y = static_cast<int>(b*sin(t) + p.y);
ptList.push_back(Point(x, y));
}
}
Canvas.h
#ifndef _CANVAS_H_
#define _CANVAS_H_
#include "Shape.h"
#include <vector>
using namespace std;
namespace Graphics {
class Canvas {
private:
int width, height;
Color bgColor;
vector<Shape*> allShapes;
unsigned char *pixels;
private:
void ConvertToBitmap();
void RemoveAllShapes();
public:
Canvas() :bgColor(Color::white), width(640), height(480), pixels(nullptr) {}
Canvas(int _width, int _height, Color _bgColor = Color::white) :
width(_width), height(_height), bgColor(_bgColor) {}
Canvas(const Canvas &c);
Canvas& operator=(const Canvas &c);
~Canvas() {
delete[]pixels;
RemoveAllShapes();
}
void Attach(const Shape &s) {
allShapes.push_back(s.Clone());
}
void ReDraw() {}
void SaveToBitmap(const char *filename);
};
}
#endif
Canvas.cpp
#include "Canvas.h"
#include "BmpIO.h"
using namespace Graphics;
Canvas::Canvas(const Canvas &c) {
bgColor = c.bgColor;
width = c.width;
height = c.height;
/*vector<Shape*> allShapes;
unsigned char *pixels;*/
unsigned char*_ptemp = new unsigned char;
_ptemp = c.pixels;
pixels = _ptemp;
vector<Shape*>temp = c.allShapes;
allShapes = temp;
}
Canvas& Canvas::operator=(const Canvas &c) {
if (this != &c) {
delete[]pixels;
for (unsigned int i = 0; i < allShapes.size(); ++i) {
delete allShapes[i];
}
bgColor = c.bgColor;
width = c.width;
height = c.height;
/*vector<Shape*> allShapes;
unsigned char *pixels;*/
unsigned char*_ptemp = new unsigned char;
_ptemp = c.pixels;
pixels = _ptemp;
vector<Shape*>temp = c.allShapes;
allShapes = temp;
}
return *this;
}
void Canvas::RemoveAllShapes() {
for (auto x : allShapes)delete x;
allShapes.clear();
}
void Canvas::ConvertToBitmap() {
if (nullptr != pixels) delete[]pixels;
pixels = nullptr;
int numPixels = width * height;
if (numPixels < 1) return;
pixels = new unsigned char[numPixels * 3];
for (int j = 0; j < numPixels; j++) {
pixels[3 * j + 0] = bgColor.r;
pixels[3 * j + 1] = bgColor.g;
pixels[3 * j + 2] = bgColor.b;
}
vector<Point> ptList;
for (auto x : allShapes) {
x->GetEdgePointList(ptList);
Color c = x->getLineColor();
for (auto p : ptList) {
if (p.x >= 0 && p.x < width && p.y>0 && p.y < height) {
int index = (p.x + p.y * width) * 3;
pixels[index + 0] = c.r;
pixels[index + 1] = c.g;
pixels[index + 2] = c.b;
}
}
}
}
void Canvas::SaveToBitmap(const char *filename) {
ConvertToBitmap();
WriteBitmap(pixels, width, height, filename);
}
BmplO.h与BmplO.cpp略