自定义标绘之二 - 定义数据模型

由于绘制的内容比较多,采用的绘制策略就是,用户先绘制那种类型的数据,这种类型的图层数据就会在下层,最后绘制的图形就会在上层。如果有遮盖的话可以通过调整透明度来修改。

在功能模块上,由于绘制的内容比较多,这就在逻辑上做了一个分层,用户已经绘制的模块,放在最下层,当前鼠标正在绘制的内容在最上层。这样就可以把鼠标当前正在操作事件和已经绘制的事件分离开来。实现了解耦。

自定义标绘之二 - 定义数据模型_第1张图片

首先要把数据模型定义出来,所有的几何数据模型继承自BaseGeo,这个基类中包含了任何一个几何模型的基本数据:
几何ID、名称、几何类型、是否显示。包围多边形等

定义一些全局使用到结构:

//用户绘制类型
enum USER_DRAW_TYPE {
	USER_DRAW_NULL = -1,
	USER_DRAW_POINT = 100,//点
	USER_DRAW_LINE,//线
	USER_DRAW_PATH,//路径
	USER_DRAW_RECT,//矩形
	USER_DRAW_POLYGON,//多边形
	USER_DRAW_CIRCLE,//圆
	USER_DRAW_PIE,//扇形
	USER_DRAW_CIRCLE_ARC,//圆弧
	USER_DRAW_TEXT,//文本
};

//绘制图形中的点要素
typedef struct tagGeoPoint {
	double lon;
	double lat;
	double alt;
	tagGeoPoint() {
		lon = 0.0;
		lat = 0.0;
		alt = 0.0;
	}

	tagGeoPoint(double x,double y,double z) {
		lon = x;
		lat = y;
		alt = z;
	}
}UserGeoPoint;

#define USER_GEO_FILE_VER 10000 //文件版本

BaseGeo

class BaseGeo {
public:
	BaseGeo(USER_DRAW_TYPE drawType);
	~BaseGeo();

	//ID
	void setGeoID(long long id) {
		_geoID = id;
	}

	long long &getGeoID() {
		return _geoID;
	}

	//名称
	void setGeoName(QString name) {
		_geoName = name;
	}
	QString&getGeoName() {
		return _geoName;
	}
	
	//类型
	void setUserDrawDataType(USER_DRAW_TYPE type) {
		_drawType = type;
	}

	USER_DRAW_TYPE&getUserDrawDataType() {
		return _drawType;
	}


	//高亮显示
	void setHightLight(bool b) {
		_bHightLight = b;
	}
	bool&getHightLight() {
		return _bHightLight;
	}

	//显示
	void setShow(bool b) {
		_bShow = b;
	}
	bool&getShow() {
		return _bShow;
	}

	QPolygon&getBound() {
		return _boundPolygon;
	}

	virtual void draw(QPainter* p);
	virtual void drawNameText(QPainter* p);

protected:
	long long _geoID = -1;//几何图形的ID
	QString _geoName;//几何图形的名称
	USER_DRAW_TYPE _drawType = USER_DRAW_NULL;//用户绘制类型

	bool _bShow = true;//是否显示
	bool _bHightLight = false;//是否高亮显示图形

	QPolygon _boundPolygon;//几何图形包围多边形
};

BaseGeo::BaseGeo(USER_DRAW_TYPE drawType) {
	_drawType = drawType;
}

BaseGeo::~BaseGeo() {
}

void BaseGeo::draw(QPainter* p) {

}

void BaseGeo::drawNameText(QPainter* p) {

}

因为在清除的时候,都需要数据清理,所以还有继承数据清理接口:

//数据清理接口
class IClearData {
public:
	IClearData();
	~IClearData();

	virtual void cleanData() = 0;
};

在定义数据模型的时候,我把数据和属性分离开来,也就是数据和显示分离。这里的数据就是具体的经纬度数据,显示属性指的是,这些数据在地图上显示的效果,比如颜色、透明度、线型、填充色等信息!

点数据模型:

class GeoPointProp;

class PointGeo :public BaseGeo, public IClearData {
public:
	PointGeo();
	~PointGeo();

	void setLon(double lon);
	double&getLon();

	void setLat(double lat);
	double&getLat();

	void setAlt(double alt);
	double&getAlt();

	void setRadius(int r);
	int&getRadius();

	void setOuterWidth(int w);
	int&getOuterWidth();

	void setOuterColor(QColor color);
	QColor&getOuterColor(); 

	void setFillColor(QColor color);
	QColor&getFillColor();

	void setAlpha(int a);
	int&getAlpha();

	//显示名称
	void setShowName(bool b);
	bool&getShowName();

	//设置点的属性
	void setPointProp(GeoPointProp* pointProp);
	GeoPointProp* getPointProp();

	virtual void draw(QPainter* p)override;
	virtual void drawNameText(QPainter* p)override;
	virtual void cleanData()override;

protected:
	double _lon = 0.0;//经度
	double _lat = 0.0;//纬度
	double _alt = 0.0;//高程

	GeoPointProp* _pointProp = nullptr;//显示属性
};

PointGeo::PointGeo() :BaseGeo(USER_DRAW_POINT) {
	_pointProp = new GeoPointProp;
}

PointGeo::~PointGeo() {
}

void PointGeo::setLon(double lon) {
	_lon = lon;
}

double& PointGeo::getLon() {
	return _lon;
}

void PointGeo::setLat(double lat) {
	_lat = lat;
}

double& PointGeo::getLat() {
	return _lat;
}

void PointGeo::setAlt(double alt) {
	_alt = alt;
}

double& PointGeo::getAlt() {
	return _alt;
}

void PointGeo::setRadius(int r) {
	_pointProp->setRadius(r);
}

int& PointGeo::getRadius() {
	return _pointProp->getRadius();
}

void PointGeo::setOuterWidth(int w) {
	_pointProp->setOuterWidth(w);
}

int& PointGeo::getOuterWidth() {
	return _pointProp->getOuterWidth();
}

void PointGeo::setOuterColor(QColor color) {
	_pointProp->setOuterColor(color);
}

QColor& PointGeo::getOuterColor() {
	return _pointProp->getOuterColor();
}

void PointGeo::setFillColor(QColor color) {
	_pointProp->setFillColor(color);
}

QColor& PointGeo::getFillColor() {
	return _pointProp->getFillColor();
}

void PointGeo::setAlpha(int a) {
	_pointProp->setAlpha(a);
}

int& PointGeo::getAlpha() {
	return _pointProp->getAlpha();
}

void PointGeo::setShowName(bool b) {
	_pointProp->setShowName(b);
}

bool& PointGeo::getShowName() {
	return _pointProp->getShowName();
}

void PointGeo::setPointProp(GeoPointProp* pointProp) {
	_pointProp->setAlpha(pointProp->getAlpha());
	_pointProp->setFillColor(pointProp->getFillColor());
	_pointProp->setOuterColor(pointProp->getOuterColor());
	_pointProp->setOuterWidth(pointProp->getOuterWidth());
	_pointProp->setRadius(pointProp->getRadius());
	_pointProp->setShowName(pointProp->getShowName());
}

GeoPointProp* PointGeo::getPointProp() {
	return _pointProp;
}

void PointGeo::draw(QPainter* p) {
	if (!_bShow){
		return;
	}
	QPoint pt;
	CoordInst()->lonlat2Screen(_lon, _lat, pt);
	if (_bHightLight) {
		p->setPen(QPen(getOuterColor(), getOuterWidth() + 2, Qt::SolidLine));
	} else {
		p->setPen(QPen(getOuterColor(), getOuterWidth(), Qt::SolidLine));

	}
	p->setBrush(getFillColor());

	p->drawEllipse(pt.x() - getRadius(), pt.y() - getRadius(), getRadius() * 2, getRadius() * 2);

	//包围多边形
	_boundPolygon = QPolygon(QRect(pt.x() - getRadius(), pt.y() - getRadius(), getRadius() * 2, getRadius() * 2));
#if 0
	p->drawPolygon(_boundPolygon);
#endif
}

void PointGeo::drawNameText(QPainter* p) {
	if (_pointProp->getShowName() &&_bShow) {//显示名称
		QPoint pt;
		CoordInst()->lonlat2Screen(_lon, _lat, pt);
		QFont font = QFont(QStringLiteral("微软雅黑"), 10);
		if (_bHightLight) {
			font.setPointSize(12);
		} else {
			font.setPointSize(10);
		}
		p->setFont(font);
		QFontMetrics fontmetrice(font);
		QRect rect = fontmetrice.boundingRect(_geoName);
		p->drawText(pt.x() - rect.width() / 2, pt.y() + getRadius() + rect.height()/2 + 5, _geoName);
	}
}

void PointGeo::cleanData() {
	if (_pointProp != nullptr) {
		delete _pointProp;
		_pointProp = nullptr;
	}
}

线数据模型:

class LineGeo :public BaseGeo, public IClearData {
public:
	LineGeo();
	~LineGeo();
	virtual void clearData();

	void setLineWidth(int w);
	int&getLineWidth();

	void setLineType(int type);
	int getLineType();

	void setLineColor(QColor color);
	QColor&getLineColor();

	void setLineAlpha(int a);
	int&getLineAlpha();

	//显示名称
	void setShowName(bool b);
	bool&getShowName();

	void addLinePoint(UserGeoPoint pt);
	QVector<UserGeoPoint>&getPoints();

	virtual void draw(QPainter* p);
	virtual void drawNameText(QPainter* p)override;
	virtual void cleanData()override;

	void setLineProp(GeoLineProp*lineProp);
	GeoLineProp*getLineProp();
private:
	QVector<UserGeoPoint> _pointList;//线绘制中的点要素
	GeoLineProp* _lineProp = nullptr;
};

#ifndef PI
#define PI 3.14159265358979323846
#endif

#ifndef DR
#define DR 0.01745329251994329577
#endif

LineGeo::LineGeo() :BaseGeo(USER_DRAW_LINE) {
	_lineProp = new GeoLineProp;
}

LineGeo::~LineGeo() {
}

void LineGeo::clearData() {
	_pointList.clear();
}

void LineGeo::setLineWidth(int w) {
	_lineProp->setLineWidth(w);
}

int& LineGeo::getLineWidth() {
	return _lineProp->getLineWidth();
}

void LineGeo::setLineType(int type) {
	_lineProp->setLineType(type);
}

int LineGeo::getLineType() {
	return _lineProp->getLineType();
}

void LineGeo::setLineColor(QColor color) {
	_lineProp->setLineColor(color);
}

QColor& LineGeo::getLineColor() {
	return _lineProp->getLineColor();
}

void LineGeo::setLineAlpha(int a) {
	_lineProp->setLineAlpha(a);
}

int& LineGeo::getLineAlpha() {
	return _lineProp->getLineAlpha();
}

void LineGeo::setShowName(bool b) {
	_lineProp->setShowName(b);
}

bool& LineGeo::getShowName() {
	return _lineProp->getShowName();
}

void LineGeo::addLinePoint(UserGeoPoint pt) {
	_pointList.push_back(pt);
}

QVector<UserGeoPoint>& LineGeo::getPoints() {
	return _pointList;
}

void LineGeo::draw(QPainter* p) {
	if (!_bShow){
		return;
	}
	p->setRenderHint(QPainter::Antialiasing, true);

	QPen pen;
	pen.setColor(getLineColor());
	if (_bHightLight){
		pen.setWidth(getLineWidth() + 2);
	} else {
		pen.setWidth(getLineWidth());
	}
	pen.setStyle((Qt::PenStyle)getLineType());
	p->setPen(pen);

	int num = _pointList.size();
	UserGeoPoint onePt;
	QPoint pt;
	QVector<QPoint> ptList;

	//包围多边形的上边的点
	QVector<QPoint> boundUpList;
	QPoint upPt;
	//包围多边形的下边的点
	QVector<QPoint> boundDownList;
	QPoint downPt;

	for (int i = 0; i < num;i++){
		onePt = _pointList.at(i);
		CoordInst()->lonlat2Screen(onePt.lon, onePt.lat, pt);
		ptList.push_back(pt);

		//原点的位置向上移动5个像素
		upPt.setX(pt.x() - 5);
		upPt.setY(pt.y() - 5);
		boundUpList.push_back(upPt);

		//原点的位置向下移动5个像素
		downPt.setX(pt.x() + 5);
		downPt.setY(pt.y() + 5);
		boundDownList.push_back(downPt);
	}

	p->drawPolyline(ptList);

	_boundPolygon = boundUpList;
	//倒转序列
	int boundNum = boundDownList.size();
	for (int k = boundNum - 1; k >= 0; k--) {
		_boundPolygon.push_back(boundDownList.at(k));
	}
#if 0
	//绘制包围多边形
	p->drawPolygon(boundUpList);
#endif
}

void LineGeo::drawNameText(QPainter* p) {
	if (_bShow&&_lineProp->getShowName() &&_pointList.size() >= 2) {//显示名称
		QPointF screenPtFirst;
		UserGeoPoint firstPt = _pointList.at(0);
		CoordInst()->lonlat2Screen(firstPt.lon, firstPt.lat, screenPtFirst);

		QPointF screenPtSecond;
		UserGeoPoint secondPt = _pointList.at(1);
		CoordInst()->lonlat2Screen(secondPt.lon, secondPt.lat, screenPtSecond);

		QFont font = QFont(QStringLiteral("微软雅黑"), 10);
		if (_bHightLight) {
			font.setPointSize(12);
		} else {
			font.setPointSize(10);
		}
		QFontMetrics fontmetrice(font);
		QRect rect = fontmetrice.boundingRect(_geoName);
		int width = rect.width();
		int height = rect.height();
		p->setFont(font);

		p->save();
		double a = QLineF(screenPtFirst, screenPtSecond).angle();
		p->translate((screenPtFirst.x() + screenPtSecond.x()) / 2 - height / 3 * 2 * sin(a*DR)
			, (screenPtFirst.y() + screenPtSecond.y()) / 2 - height / 3 * 2 * cos(a*DR));
		(a > 90 && a < 270) ? p->rotate(-a + 180) : p->rotate(-a);
		
		QRect r(-width / 2, -height / 2, width + 2, height + 2);
#if 0
		p->drawRect(r);
#endif
		p->drawText(QRect(r.x() + 1, r.y() + 1, r.width(), r.height()), _geoName);
		p->restore();
	}
}

void LineGeo::cleanData() {
	if (_lineProp != nullptr) {
		delete _lineProp;
		_lineProp = nullptr;
	}
	_pointList.clear();
}

void LineGeo::setLineProp(GeoLineProp*lineProp) {
	_lineProp->setLineColor(lineProp->getLineColor());
	_lineProp->setLineType(lineProp->getLineType());
	_lineProp->setLineWidth(lineProp->getLineWidth());
	_lineProp->setShowName(lineProp->getShowName());
	_lineProp->setLineAlpha(lineProp->getLineAlpha());
}

GeoLineProp* LineGeo::getLineProp() {
	return _lineProp;
}

多边形数据模型:

class PolygonGeo :public BaseGeo, public IClearData {
public:
	PolygonGeo();
	~PolygonGeo();


	void setLineWidth(int w);
	int&getLineWidth();

	void setLineType(int type);
	int getLineType();

	void setLineColor(QColor color);
	QColor&getLineColor();

	void setFillColor(QColor color);
	QColor&getFillColor();

	void setUseFillColor(bool b);
	bool&getUseFillColor();

	void setAlpha(int alpha);
	int&getAlpha();

	//显示名称
	void setShowName(bool b);
	bool&getShowName();

	void addPolygonPoint(UserGeoPoint pt);
	QVector<UserGeoPoint>&getPoints();

	void setPolygonProp(GeoPolygonProp*polygonProp);
	GeoPolygonProp* getPolygonProp();

	virtual void draw(QPainter* p)override;
	virtual void drawNameText(QPainter* p)override;
	virtual void cleanData()override;
private:

	QVector<UserGeoPoint> _pointList;

	GeoPolygonProp* _polygonProp = nullptr;
};

#ifndef PI
#define PI 3.14159265358979323846
#endif

#ifndef DR
#define DR 0.01745329251994329577
#endif

PolygonGeo::PolygonGeo() :BaseGeo(USER_DRAW_POLYGON) {
	_polygonProp = new GeoPolygonProp;
}

PolygonGeo::~PolygonGeo() {
}

void PolygonGeo::setLineWidth(int w) {
	_polygonProp->setLineWidth(w);
}

int& PolygonGeo::getLineWidth() {
	return _polygonProp->getLineWidth();
}

void PolygonGeo::setLineType(int type) {
	_polygonProp->setLineType(type);
}

int PolygonGeo::getLineType() {
	return _polygonProp->getLineType();
}

void PolygonGeo::setLineColor(QColor color) {
	_polygonProp->setLineColor(color);
}

QColor& PolygonGeo::getLineColor() {
	return _polygonProp->getLineColor();
}

void PolygonGeo::setFillColor(QColor color) {
	_polygonProp->setFillColor(color);
}

QColor& PolygonGeo::getFillColor() {
	return _polygonProp->getFillColor();
}

void PolygonGeo::setUseFillColor(bool b) {
	_polygonProp->setUseFillColor(b);
}

bool& PolygonGeo::getUseFillColor() {
	return _polygonProp->getUseFillColor();
}

void PolygonGeo::setAlpha(int alpha) {
	_polygonProp->setAlpha(alpha);
}

int& PolygonGeo::getAlpha() {
	return _polygonProp->getAlpha();
}

void PolygonGeo::setShowName(bool b) {
	_polygonProp->setShowName(b);
}

bool& PolygonGeo::getShowName() {
	return _polygonProp->getShowName();
}

void PolygonGeo::addPolygonPoint(UserGeoPoint pt) {
	_pointList.push_back(pt);
}

QVector<UserGeoPoint>& PolygonGeo::getPoints() {
	return _pointList;
}

void PolygonGeo::setPolygonProp(GeoPolygonProp*polygonProp) {
	_polygonProp->setAlpha(polygonProp->getAlpha());
	_polygonProp->setFillColor(polygonProp->getFillColor());
	_polygonProp->setLineColor(polygonProp->getLineColor());
	_polygonProp->setLineType(polygonProp->getLineType());
	_polygonProp->setLineWidth(polygonProp->getLineWidth());
	_polygonProp->setUseFillColor(polygonProp->getUseFillColor());
	_polygonProp->setShowName(polygonProp->getShowName());
}

GeoPolygonProp* PolygonGeo::getPolygonProp() {
	return _polygonProp;
}

void PolygonGeo::draw(QPainter* p) {
	if (!_bShow) {
		return;
	}
	p->setRenderHint(QPainter::Antialiasing, true);

	if (_bHightLight){
		p->setPen(QPen(getLineColor(), getLineWidth() + 2, (Qt::PenStyle)getLineType()));
	} else {
		p->setPen(QPen(getLineColor(), getLineWidth(), (Qt::PenStyle)getLineType()));

	}
	if (getUseFillColor()) {
		p->setBrush(getFillColor());
	}

	//绘制多边形
	UserGeoPoint onePt;
	QPoint pt;
	QVector<QPoint> ptList;
	int num = _pointList.size();
	for (int i = 0; i < num; i++) {
		onePt = _pointList.at(i);
		CoordInst()->lonlat2Screen(onePt.lon, onePt.lat, pt);
		ptList.push_back(pt);
	}

	p->drawPolygon(ptList);

	//包围多边形
	_boundPolygon = QPolygon(ptList);
}

void PolygonGeo::drawNameText(QPainter* p) {
	if (_bShow&&_polygonProp->getShowName() &&_pointList.size() >= 2) {//显示名称
		QPointF screenPtFirst;
		UserGeoPoint firstPt = _pointList.at(0);
		CoordInst()->lonlat2Screen(firstPt.lon, firstPt.lat, screenPtFirst);

		QPointF screenPtSecond;
		UserGeoPoint secondPt = _pointList.at(1);
		CoordInst()->lonlat2Screen(secondPt.lon, secondPt.lat, screenPtSecond);

		QFont font = QFont(QStringLiteral("微软雅黑"), 10);
		if (_bHightLight) {
			font.setPointSize(12);
		} else {
			font.setPointSize(10);
		}
		QFontMetrics fontmetrice(font);
		QRect rect = fontmetrice.boundingRect(_geoName);
		int width = rect.width();
		int height = rect.height();
		p->setFont(font);

		p->save();
		double a = QLineF(screenPtFirst, screenPtSecond).angle();
		p->translate((screenPtFirst.x() + screenPtSecond.x()) / 2 - height / 3 * 2 * sin(a*DR)
			, (screenPtFirst.y() + screenPtSecond.y()) / 2 - height / 3 * 2 * cos(a*DR));
		(a > 90 && a < 270) ? p->rotate(-a + 180) : p->rotate(-a);

		QRect r(-width / 2, -height / 2, width + 2, height + 2);
#if 0
		p->drawRect(r);
#endif
		p->drawText(QRect(r.x() + 1, r.y() + 1, r.width(), r.height()), _geoName);
		p->restore();
	}
}

void PolygonGeo::cleanData() {
	if (_polygonProp != nullptr) {
		delete _polygonProp;
		_polygonProp = nullptr;
	}
	_pointList.clear();
}

矩形模型:

class RectGeo :public BaseGeo, public IClearData {
public:
	RectGeo();
	~RectGeo();

	void setLineWidth(int w);
	int&getLineWidth();

	void setLineType(int type);
	int getLineType();

	void setLineColor(QColor color);
	QColor&getLineColor();

	void setFillColor(QColor color);
	QColor&getFillColor();

	void setUseFillColor(bool b);
	bool&getUseFillColor();

	void setAlpha(int alpha);
	int&getAlpha();

	//显示名称
	void setShowName(bool b);
	bool&getShowName();

	void setLeftTopPoint(UserGeoPoint ltPt);
	UserGeoPoint&getLeftTopPoint();

	void setRightBottomPoint(UserGeoPoint ltPt);
	UserGeoPoint&getRightBottomPoint();

	void setRectProp(GeoRectProp* rectProp);
	GeoRectProp* getRectProp();

	virtual void draw(QPainter* p);
	virtual void drawNameText(QPainter* p)override;
	virtual void cleanData()override;
private:

	UserGeoPoint _leftTopPoint;//左上角点
	UserGeoPoint _rightBottomPoint;//右下角点

	GeoRectProp* _rectProp = nullptr;
};

RectGeo::RectGeo() :BaseGeo(USER_DRAW_RECT) {
	_rectProp = new GeoRectProp;
}

RectGeo::~RectGeo() {
}

void RectGeo::setLineWidth(int w) {
	_rectProp->setLineWidth(w);
}

int& RectGeo::getLineWidth() {
	return _rectProp->getLineWidth();
}

void RectGeo::setLineType(int type) {
	_rectProp->setLineType(type);
}

int RectGeo::getLineType() {
	return _rectProp->getLineType();
}

void RectGeo::setLineColor(QColor color) {
	_rectProp->setLineColor(color);
}

QColor& RectGeo::getLineColor() {
	return _rectProp->getLineColor();
}

void RectGeo::setFillColor(QColor color) {
	_rectProp->setFillColor(color);
}

QColor& RectGeo::getFillColor() {
	return _rectProp->getFillColor();
}

void RectGeo::setUseFillColor(bool b) {
	_rectProp->setUseFillColor(b);
}

bool& RectGeo::getUseFillColor() {
	return _rectProp->getUseFillColor();
}

void RectGeo::setAlpha(int alpha) {
	_rectProp->setAlpha(alpha);
}

int& RectGeo::getAlpha() {
	return _rectProp->getAlpha();
}

void RectGeo::setShowName(bool b) {
	_rectProp->setShowName(b);
}

bool& RectGeo::getShowName() {
	return _rectProp->getShowName();
}

void RectGeo::setLeftTopPoint(UserGeoPoint ltPt) {
	_leftTopPoint = ltPt;
}

UserGeoPoint& RectGeo::getLeftTopPoint() {
	return _leftTopPoint;
}

void RectGeo::setRightBottomPoint(UserGeoPoint ltPt) {
	_rightBottomPoint = ltPt;
}

UserGeoPoint& RectGeo::getRightBottomPoint() {
	return _rightBottomPoint;
}

void RectGeo::setRectProp(GeoRectProp* rectProp) {
	_rectProp->setAlpha(rectProp->getAlpha());
	_rectProp->setFillColor(rectProp->getFillColor());
	_rectProp->setLineColor(rectProp->getLineColor());
	_rectProp->setLineType(rectProp->getLineType());
	_rectProp->setLineWidth(rectProp->getLineWidth());
	_rectProp->setUseFillColor(rectProp->getUseFillColor());
	_rectProp->setShowName(rectProp->getShowName());
}

GeoRectProp* RectGeo::getRectProp() {
	return _rectProp;
}

void RectGeo::draw(QPainter* p) {
	if (!_bShow){
		return;
	}
	p->setRenderHint(QPainter::Antialiasing, true);

	if (_bHightLight) {
		p->setPen(QPen(getLineColor(), getLineWidth() + 2, (Qt::PenStyle)getLineType()));
	} else {
		p->setPen(QPen(getLineColor(), getLineWidth(), (Qt::PenStyle)getLineType()));
	}
	if (getUseFillColor()) {
		p->setBrush(getFillColor());
	}

	QPointF pt1, pt2;
	CoordInst()->lonlat2Screen(_leftTopPoint.lon, _leftTopPoint.lat, pt1);
	CoordInst()->lonlat2Screen(_rightBottomPoint.lon, _rightBottomPoint.lat, pt2);
	p->drawRect(QRectF(pt1, pt2));

	//包围多边形
	_boundPolygon = QPolygon(QRect(QPoint(pt1.x(), pt1.y()), QPoint(pt2.x(), pt2.y())));
}

void RectGeo::drawNameText(QPainter* p) {
	if (_bShow&&_rectProp->getShowName()) {
		QFont font = QFont(QStringLiteral("微软雅黑"), 10);
		if (_bHightLight) {
			font.setPointSize(12);
		} else {
			font.setPointSize(10);
		}
		QFontMetrics fontmetrice(font);
		QRect rect = fontmetrice.boundingRect(_geoName);
		int width = rect.width();
		int height = rect.height();
		p->setFont(font);

		QPointF pt1, pt2;
		CoordInst()->lonlat2Screen(_leftTopPoint.lon, _leftTopPoint.lat, pt1);
		CoordInst()->lonlat2Screen(_rightBottomPoint.lon, _rightBottomPoint.lat, pt2);
		QRectF rectText = QRectF(pt1, pt2);

		int textX = rectText.left() + (rectText.width() - width) / 2;
		int textY = rectText.top() - height - 1;

		p->drawText(QRect(textX + 1, textY + 1, width, height), _geoName);

	}
}

void RectGeo::cleanData() {
	if (_rectProp != nullptr) {
		delete _rectProp;
		_rectProp = nullptr;
	}
}

圆形数据模型

class CircleGeo :public BaseGeo,public IClearData {
public:
	CircleGeo();
	~CircleGeo();

	void setCenterPoint(UserGeoPoint pt);
	UserGeoPoint&getCenterPoint();

	void setRightBottomPoint(UserGeoPoint pt);
	UserGeoPoint&getRightBottomPoint();

	void setRadius(double r);
	double&getRadius();

	void setAzimuth(double a);
	double&getAzimuth();

	void setLineColor(QColor color);
	QColor&getLineColor();

	void setLineType(int s);
	int getLineType();

	void setLineWidth(int w);
	int&getLineWidth();

	void setFillColor(QColor color);
	QColor&getFillColor();

	void setUseFillColor(bool b);
	bool&getUseFillColor();

	void setAlpha(int a);
	int&getAlpha();

	//显示名称
	void setShowName(bool b);
	bool&getShowName();

	void setCircleProp(GeoCircleProp*circleProp);
	GeoCircleProp* getCircleProp();

	virtual void draw(QPainter* p)override;
	virtual void drawNameText(QPainter* p)override;
	virtual void cleanData()override;

private:
	//绘制投影变形后的圆
	void drawProjCircle(QPainter* p);
private:

	UserGeoPoint _centerPoint;//中心点
	UserGeoPoint _rightBottomPoint;//右下角的点
	double _radius = 0;//半径-米
	double _azimuth = 0.0;//右下角在中心点的方位角
	
	GeoCircleProp* _circleProp = nullptr;
};

CircleGeo::CircleGeo() :BaseGeo(USER_DRAW_CIRCLE) {
	_circleProp = new GeoCircleProp;
}

CircleGeo::~CircleGeo() {
}

void CircleGeo::setCenterPoint(UserGeoPoint pt) {
	_centerPoint = pt;
}

UserGeoPoint& CircleGeo::getCenterPoint() {
	return _centerPoint;
}

void CircleGeo::setRightBottomPoint(UserGeoPoint pt) {
	_rightBottomPoint = pt;
}

UserGeoPoint& CircleGeo::getRightBottomPoint() {
	return _rightBottomPoint;
}

void CircleGeo::setRadius(double r) {
	_radius = r;
}

double& CircleGeo::getRadius() {
	return _radius;
}

void CircleGeo::setAzimuth(double a) {
	_azimuth = a;
}

double& CircleGeo::getAzimuth() {
	return _azimuth;
}

void CircleGeo::setLineColor(QColor color) {
	_circleProp->setLineColor(color);
}

QColor& CircleGeo::getLineColor() {
	return _circleProp->getLineColor();
}

void CircleGeo::setLineType(int s) {
	_circleProp->setLineType(s);
}

int CircleGeo::getLineType() {
	return _circleProp->getLineType();
}

void CircleGeo::setLineWidth(int w) {
	_circleProp->setLineWidth(w);
}

int& CircleGeo::getLineWidth() {
	return _circleProp->getLineWidth();
}

void CircleGeo::setFillColor(QColor color) {
	_circleProp->setFillColor(color);
}

QColor& CircleGeo::getFillColor() {
	return _circleProp->getFillColor();
}

void CircleGeo::setUseFillColor(bool b) {
	_circleProp->setUseFillColor(b);
}

bool& CircleGeo::getUseFillColor() {
	return _circleProp->getUseFillColor();
}

void CircleGeo::setAlpha(int a) {
	_circleProp->setAlpha(a);
}

int& CircleGeo::getAlpha() {
	return _circleProp->getAlpha();
}

void CircleGeo::setShowName(bool b) {
	_circleProp->setShowName(b);
}

bool& CircleGeo::getShowName() {
	return _circleProp->getShowName();
}


void CircleGeo::setCircleProp(GeoCircleProp*circleProp) {
	_circleProp->setAlpha(circleProp->getAlpha());
	_circleProp->setFillColor(circleProp->getFillColor());
	_circleProp->setLineColor(circleProp->getLineColor());
	_circleProp->setLineType(circleProp->getLineType());
	_circleProp->setLineWidth(circleProp->getLineWidth());
	_circleProp->setUseFillColor(circleProp->getUseFillColor());
	_circleProp->setShowName(circleProp->getShowName());
}

GeoCircleProp* CircleGeo::getCircleProp() {
	return _circleProp;
}

void CircleGeo::draw(QPainter* p) {
	if (!_bShow) {
		return;
	}
	p->setRenderHint(QPainter::Antialiasing, true);

	if (_bHightLight) {
		p->setPen(QPen(getLineColor(), getLineWidth() +2, (Qt::PenStyle)getLineType()));
	} else {
		p->setPen(QPen(getLineColor(), getLineWidth(), (Qt::PenStyle)getLineType()));
	}

	if (getUseFillColor()) {
		p->setBrush(getFillColor());
	}

	QPoint ptCenter;
	CoordInst()->lonlat2Screen(_centerPoint.lon, _centerPoint.lat, ptCenter);
	if (_bHightLight) {
		p->drawEllipse(ptCenter, 2, 2);//画圆心
	}

#if 0
	QPoint ptRightBottom;
	CoordInst()->lonlat2Screen(_rightBottomPoint.lon, _rightBottomPoint.lat, ptRightBottom);
	double radias = sqrt(double(ptCenter.x() - ptRightBottom.x())*(ptCenter.x() - ptRightBottom.x())
		+ (ptCenter.y() - ptRightBottom.y()) * (ptCenter.y() - ptRightBottom.y()));

	//绘制圆所在的矩形,需要的参数圆心点(矩形的中点)坐标和中点到矩形两边的距离
	p->drawEllipse(ptCenter, (int)(radias), (int)(radias));
	QRect rect(ptCenter, ptRightBottom);
	p->drawRect(rect);//画矩形

					  //包围多边形
	_boundPolygon = QPolygon(QRect(QPoint(ptCenter.x() - radias, ptCenter.y() - radias)
		, QPoint(ptCenter.x() + radias, ptCenter.y() + radias)));
#else
	drawProjCircle(p);
#endif

}

void CircleGeo::drawNameText(QPainter* p) {
	if (_bShow&&_circleProp->getShowName()) {//显示名称
		QFont font = QFont(QStringLiteral("微软雅黑"), 10);
		if (_bHightLight) {
			font.setPointSize(12);
		} else {
			font.setPointSize(10);
		}
		QFontMetrics fontmetrice(font);
		QRect rect = fontmetrice.boundingRect(_geoName);
		int width = rect.width();
		int height = rect.height();
		p->setFont(font);

		QPoint ptCenter;
		CoordInst()->lonlat2Screen(_centerPoint.lon, _centerPoint.lat, ptCenter);

		QPoint ptRightBottom;
		CoordInst()->lonlat2Screen(_rightBottomPoint.lon, _rightBottomPoint.lat, ptRightBottom);
		double radias = sqrt(double(ptCenter.x() - ptRightBottom.x())*(ptCenter.x() - ptRightBottom.x())
			+ (ptCenter.y() - ptRightBottom.y()) * (ptCenter.y() - ptRightBottom.y()));

		int len = _geoName.length();
		QPoint ptText = QPoint(0, -radias - 2);
		ptText += ptCenter;
		ptText.setX(ptText.x() - width / 2);

		p->drawText(ptText, _geoName);
	}
}

void CircleGeo::cleanData() {
	if (_circleProp != nullptr) {
		delete _circleProp;
		_circleProp = nullptr;
	}
}

void CircleGeo::drawProjCircle(QPainter* p) {
	QPoint ptCenter;
	CoordInst()->lonlat2Screen(_centerPoint.lon, _centerPoint.lat, ptCenter);

	double targetLon = 0.0, targetLat = 0.0, targetAlt = 0.0;
	QPolygon polygon;
	for (double i = 0; i <= 360; i += 1.0) {//每隔1度计算一点,多个点连接在一起就是近似一条弧线
		CoordTransCalc::getPositionFromDisAndAzi(_centerPoint.lon, _centerPoint.lat, _centerPoint.alt
			, _radius, _centerPoint.alt, i
			, targetLon, targetLat, targetAlt);

		QPoint pt;
		if (targetLon != 0.0&& targetLat != 0.0) {
			CoordInst()->lonlat2Screen(targetLon, targetLat, pt);
			polygon.push_back(pt);
		}
	}
	p->drawPolygon(polygon);

	//包围多边形
	_boundPolygon = polygon;
} 

你可能感兴趣的:(c++,qt)