C++程序设计六(类的继承、多态性)

编写一个平面图形系统,实现类似Windows画图的功能:可以绘制基本的图形,比如矩形,圆形、直线段、椭圆等,可以设置形状的线条颜色/粗细/线型。要求:

1)定义一个命名空间Graphics;在该空间中开发图形系统。

2)编写一个表示画布的类Canvas,所有图形由该类维护,Canvas类有一个方法是保存绘图结果到一个bmp文件。保存bmp文件的代码在BmpIO.h和BmpIO.cpp中。Canvas类另一个方法是添加基本图形实例到画布中。其它方法根据需要自行添加。

3)编写抽象基类Shape,表示抽象的图形;

4)从Shape派生出至少两个子类,表示两种不同的图形;

5)在main函数中,生成Canvas对象,并向该对象添加几种图形实例,然后保存成位图文件。

6)尝试在Canvas中添加一个填充功能,使用FloodFill算法,从指定的种子点开始,用指定的颜色,填充一个封闭的区域。

shape.h

#ifndef _SHAPE_H_
#define _SHAPE_H_
#include 
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 &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 &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 &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 &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 &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 &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(r*cos(t) + p.x);
		int y = static_cast(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 &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(a*cos(t) + p.x);
		int y = static_cast(b*sin(t) + p.y);
		ptList.push_back(Point(x, y));
	}
}

Canvas.h

#ifndef _CANVAS_H_
#define _CANVAS_H_
#include "Shape.h"
#include 

using namespace std;
namespace Graphics {

	class Canvas {
	private:
		int width, height;
		Color bgColor;
		vector 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 allShapes;
	unsigned char *pixels;*/
	unsigned char*_ptemp = new unsigned char;
	_ptemp = c.pixels;
	pixels = _ptemp;
	vectortemp = 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 allShapes;
		unsigned char *pixels;*/
		unsigned char*_ptemp = new unsigned char;
		_ptemp = c.pixels;
		pixels = _ptemp;
		vectortemp = 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 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略

展示效果:

你可能感兴趣的:(实验,c++,windows)