很多的业务项目中,都会用到二维地图,二维地图功能简洁,并且很多在很多的业务中采用,维护难度也比三维地图小一些。而开发二维地图的开源库有QGis, Mapwingis等。
采用mapwingis开发了一个二维地图组件,可以实现常用的地图功能。比如地图的放大,缩小,移动,添加矩形,添加圆形,测量距离,获取经纬度等常用功能。并且提供了较多的接口,方便后期二次开发和维护等。组件采用vs2015+qt5.9.8开发。
使用地图接口的代码为:
//主要有mymap.h, mymap.cpp, main.cpp三个代码文件
//mymap.h
#pragma once
#include <QtWidgets/QDialog>
#include <QTimer>
#include "ui_mymap.h"
#include "hlMap/imapview.h"
#include "hlLinker/IEntity.h"
class CEngine;
class mymap : public QDialog
{
Q_OBJECT
public:
mymap(QWidget* parent = Q_NULLPTR);
virtual ~mymap();
private slots:
/*
@brief 刷新兵力数据
*/
void slotTimeout();
/*
@brief 鼠标在地图点击信号
@param btn 鼠标按键,1表示左键,2表示右键
@param lon 经度
@param lat 纬度
*/
void slotMouseClicked(int btn, double lon, double lat);
/*
@brief 鼠标在地图双击信号
@param btn 鼠标按键,1表示左键,2表示右键
@param lon 经度
@param lat 纬度
*/
void slotMouseDoubleClicked(int btn, double lon, double lat);
/*
@brief 鼠标位置改变
@param lon 经度
@param lat 纬度
*/
void slotMouseMoved(double lon, double lat);
图元信号
/*
@brief 兵力增加消息
@param id 兵力ID
*/
void slotForceJoined(unsigned int id);
/*
@brief 兵力删除消息
@param id 兵力ID
*/
void slotForceResigned(unsigned int id);
/*
@brief 兵力选中消息
@param id 兵力ID
@param selected true表示选中,false表示未选中
*/
void slotForceSelected(unsigned int id, bool selected);
/*
@brief 新产生标绘
@param id 标绘ID
*/
void slotGraphicsAdded(unsigned int id);
/*
@brief 标绘删除
@param id 标绘ID
*/
void slotGraphicsRemoved(unsigned int id);
/*
@brief 标绘选中消息
@param id 标绘ID
@param selected true表示选中,false表示未选中
*/
void slotGraphicsSelected(unsigned int id, bool selected);
private:
Ui::MapTestClass ui;
CEngine* _engine;
QTimer _timer;
hlLinker::EntityPtrType _pentity;
hlgis::IMapView* _pmapview;
};
//mymap.cpp
#include "mymap.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QMenu>
#include <QGraphicsItem>
#include "Math/Geography.h"
#include "Math/Constant.h"
#include "Math/RandomGenerator.h"
#include "Thread/Thread.h"
#include "Utility/JsonFile.h"
#include "KernelDefine.inl"
#include "hlMap/iforcemgr.h"
#include "hlMap/igraphicsmgr.h"
#include "hlLinker/IEntity.h"
#include "hlLinker/SimLinker.h"
#include "ui_mywgt.h"
#define TEST_FORCE_NUM 0
class CEngine : public Common::CThread
{
public:
CEngine(hlgis::IForceManager* forcemgr) : _forcemgr(forcemgr) {
Start();
}
virtual ~CEngine() {
Stop();
}
protected:
virtual void run() {
{// 性能测试
for (int i = 0; i < TEST_FORCE_NUM; ++i)
{
hlLinker::EntityPtrType e = _forcemgr->getForce(i + 1);
if (e == NULL) return;
double lon = e->getLon();
double lat = e->getLat();
double heading = e->getHeading();
double dlon, dlat;
Common::dr_to_ll(lon, lat, heading, 100, dlon, dlat);
e->setLon(dlon);
e->setLat(dlat);
}
}
_tsleep(1);
}
private:
hlgis::IForceManager* _forcemgr;
};
class MyWgt : public QWidget
{
public:
MyWgt(QWidget* parent) : QWidget(parent){
_ui.setupUi(this);
}
private:
Ui_mywgt _ui;
};
mymap::mymap(QWidget* parent)
: QDialog(parent)
{
ui.setupUi(this);
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
//创建地图控件
_pmapview = hlgis::create_mapview();
//加载地图
if (_pmapview->load())
{
//将地图加入窗口
QHBoxLayout* layout = new QHBoxLayout(ui.widget);
layout->addWidget(_pmapview->widget());
QObject* mapview_bus = _pmapview->msgBus();
MyWgt* mywgt = new MyWgt(_pmapview->widget());
bool bConnect = true;
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigMouseClicked(int, double, double)),
this, SLOT(slotMouseClicked(int, double, double)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigMouseDoubleClicked(int, double, double)),
this, SLOT(slotMouseDoubleClicked(int, double, double)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigMouseMoved(double, double)),
this, SLOT(slotMouseMoved(double, double)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigForceJoined(unsigned int)),
this, SLOT(slotForceJoined(unsigned int)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigForceResigned(unsigned int)),
this, SLOT(slotForceResigned(unsigned int)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigForceSelected(unsigned int, bool)),
this, SLOT(slotForceSelected(unsigned int, bool)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigGraphicsAdded(unsigned int)),
this, SLOT(slotGraphicsAdded(unsigned int)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigGraphicsRemoved(unsigned int)),
this, SLOT(slotGraphicsRemoved(unsigned int)));
Q_ASSERT(bConnect);
bConnect &= (bool)connect(mapview_bus, SIGNAL(sigGraphicsSelected(unsigned int, bool)),
this, SLOT(slotGraphicsSelected(unsigned int, bool)));
Q_ASSERT(bConnect);
//_pmapview->setOwner("zhangsan");
_pmapview->setSyncGroup("mygroup");
_pmapview->setEventWindowVisible(false);
QAction* myact = _pmapview->menu()->addAction(u8"我的地图菜单");
double lon = 120, lat = 22;
double x, y;
hlgis::map_to_screen(lon, lat, x, y);
double lon1, lat1;
hlgis::screen_to_map(x, y, lon1, lat1);
double centerlon = 114.2081;
double centerlat = 30.7838;
_pmapview->centerOn(centerlon, centerlat);
hlgis::IForceManager* forcemgr = _pmapview->forceMgr();
// 隐藏标识为myeffect下面的原始包络
_pmapview->setLayerVisible("effects/myeffect/self/origin", false);
{
_pentity = NULL;
const char* props1 = R"({
"id":123,
"name":"001_1",
"entity":123,
"iff":3,
"lon":115.0,
"lat":21.0,
"alt":100.0,
"heading":0.0,
"roll":0.0,
"pitch":0.0})";
hlLinker::EntityPtrType e = forcemgr->addForce(props1);
{
unsigned int effectid = e->addEffect(1);
const char* estr = R"({
"symbol":"myeffect",
"fuse":true,
"framecolor":"#FF0000",
"fillcolor":"#1F00FF00",
"points":[["30-60#200000",3000]]})";
e->setEffect(effectid, estr);
}
{
const char* props = R"({
"id":456,
"name":"001_2",
"entity":123,
"iff":3,
"lon":116.0,
"lat":22.0,
"alt":100.0,
"heading":0.0,
"roll":0.0,
"pitch":0.0})";
e = forcemgr->addForce(props);
}
{
unsigned int effectid = e->addEffect(2);
const char* estr2 = u8R"({
"type":2,
"label":"我的特效线",
"color":"#9F00FF00",
"width" : 10,
"src" : "123",
"dest" : "456"})";
e->setEffect(effectid, estr2);
}
{
unsigned int effectid = e->addEffect(1);
/* const char* estr = R"({
"symbol":"myeffect",
"fuse":true,
"framecolor":"#FF0000",
"fillcolor":"#1F00FF00",
"points":[[500000,500000,500000,500000,500000,300000,300000,300000,300000,300000,300000,300000,300000,300000,300000,300000,300000,350000,350000,350000,350000,350000,350000,350000,3000]]})";*/
const char* estr = R"({
"symbol":"myeffect",
"fuse":true,
"framecolor":"#FF0000",
"fillcolor":"#1F00FF00",
"points":[[300000,300000,300000,300000,"30-60#500000","80-160#100000",3000]]})";
e->setEffect(effectid, estr);
}
_pentity = e;
int nTest = 0;
}
{
Common::CUniformDistributionRandom lonrand, latrand, headingrand;
lonrand.Input(-180, 180);
latrand.Input(-90, 90);
//lonrand.Input(90, 130);
//latrand.Input(0, 60);
headingrand.Input(0, 360);
for (int i = 0; i < TEST_FORCE_NUM; ++i)
{
double lon = lonrand.Generate();
double lat = latrand.Generate();
double heading = headingrand.Generate();
char props[1024];
_tsprintf(props, R"({
"id":%d,
"name":"J-10_1",
"entity":460,
"iff":%d,
"lon":%f,
"lat":%f,
"alt":0,
"heading":%f,
"roll":0.0,
"pitch":0.0})", i + 1, i % 7 + 1, lon, lat, heading);
hlLinker::EntityPtrType e = forcemgr->addForce(props);
}
_engine = new CEngine(forcemgr);
}
hlgis::IGraphicsManager* graphicsmgr = _pmapview->graphicsMgr();
{
const char* props = R"({
"id":555,
"name" : "area_1",
"type" : "area",
"shape" : {
"framecolor": "#FF0000",
"fillcolor" : ""
},
"anchors" : [
{"lon": 120, "lat" : 22},
{"lon": 120, "lat" : 21},
{"lon": 119, "lat" : 21},
{"lon": 119, "lat" : 22}
]})";
//hlLinker::GraphicsPtrType ovl = graphicsmgr->addGraphics(props);
int nTest = 0;
}
{
//const char* props = R"({
// "id":0,
// "type" : "route",
// "shape" : {
// "framecolor": "#FF0000",
// "fillcolor" : ""
// },
// "anchors" : [
// {"lon": 115.0, "lat" : 21.0},
// {"lon": 120, "lat" : 22}
// ]})";
const char* props = R"({
"type" : "route",
"shape" : {
"framecolor": "#FF0000",
"fillcolor" : ""
}})";
//hlLinker::GraphicsPtrType ovl = graphicsmgr->addGraphics(props);
//ovl->addAnchor(115, 21, 0);
//ovl->addAnchor(120, 22, 0);
int nTest = 0;
}
//_timer.start(1000);
}
}
mymap::~mymap()
{
}
void mymap::slotTimeout()
{
{// 单例功能测试
if (_pentity == NULL) return;
double lon = _pentity->getLon();
double lat = _pentity->getLat();
double heading = _pentity->getHeading();
double dlon, dlat;
Common::dr_to_ll(lon, lat, heading, 1000, dlon, dlat);
_pentity->setLon(dlon);
_pentity->setLat(dlat);
}
}
void mymap::slotMouseClicked(int btn, double lon, double lat)
{
}
void mymap::slotMouseDoubleClicked(int btn, double lon, double lat)
{
}
void mymap::slotMouseMoved(double lon, double lat)
{
}
void mymap::slotForceJoined(unsigned int id)
{
}
void mymap::slotForceResigned(unsigned int id)
{
}
void mymap::slotForceSelected(unsigned int id, bool selected)
{
}
void mymap::slotGraphicsAdded(unsigned int id)
{
}
void mymap::slotGraphicsRemoved(unsigned int id)
{
}
void mymap::slotGraphicsSelected(unsigned int id, bool selected)
{
}
//main.cpp
#include "mymap.h"
#include <QtWidgets/QApplication>
#include <QTextCodec>
#include "Log/TxtLog.h"
#include "Utility/OSHelper.h"
#include "Qt/qtCommon.h"
int main(int argc, char* argv[])
{
SYSTEM_LOG_RENAME("map-test");
//支持中文格式
QTextCodec::setCodecForLocale(QTextCodec::codecForName("system"));
// 加入插件路径
std::string home = Common::env_value("DBDK_HOME");
if (home.empty())home = ".";
QString lib_path = UDQ_L8(home.c_str()) + ("/plugins");
QGuiApplication::addLibraryPath(lib_path);
QGuiApplication::addLibraryPath(lib_path + "/platforms");
QGuiApplication::addLibraryPath(lib_path + "/sqldrivers");
QGuiApplication::addLibraryPath(lib_path + "/imageformats");
QApplication a(argc, argv);
mymap w;
w.showMaximized();
return a.exec();
}
//运行后的界面如下: