由于绘制的内容比较多,采用的绘制策略就是,用户先绘制那种类型的数据,这种类型的图层数据就会在下层,最后绘制的图形就会在上层。如果有遮盖的话可以通过调整透明度来修改。
在功能模块上,由于绘制的内容比较多,这就在逻辑上做了一个分层,用户已经绘制的模块,放在最下层,当前鼠标正在绘制的内容在最上层。这样就可以把鼠标当前正在操作事件和已经绘制的事件分离开来。实现了解耦。
首先要把数据模型定义出来,所有的几何数据模型继承自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;
}