有关 QML QtLocation 的 Plugin 的使用问题
-
这个
Plugin
是可以提供具体地图的地图在线插件,使用方法是:qml
Plugin { name: "here" PluginParameter { name: "here.app_id"; value: "myapp" } PluginParameter { name: "here.token"; value: "abcdefg12345" } }
c++
QMap<QString,QVariant> params; params["here.app_id"] = "myapp"; params["here.token"] = "abcdefg12345"; QGeoServiceProvider *gsp = new QGeoServiceProvider("here", params);
然后将其设置给
Map
,用来显示实际的地图。然后 Qt 提供了三个内建的地图在线插件
here
,osm
,mapbox
三个,但是我们身处中国,自然有自己的在线地图,例如百度地图。这里的问题是,怎么把百度的在线地图封装成 QML 的地图在线插件?
-
百度地图在中国范围内是最全的,不过呢,这里面的技术是他们的,目前提供了JS的API,不知道可不可以和Qt相结合。
-
http://lbsyun.baidu.com/index.php?title=webapi
看来应该是可以的。
另外
Qt5.5.1\5.5\Src\qtlocation\src\plugins\geoservices\nokia
这个路径下有here
地图的封装实现。我不知道有没有人去研究过。
-
@qyvlik 好像
OpenStreetMap
是可用的吧。
-
@jcy 其他的,例如
here
还有mapbox
要设置 appid 和密钥。
-
@qyvlik here是商业的,好像现在我们访问不了吧,被收购了。访问http://heremaps.cn,直接跳转了,没办法打开地图。
mapbox
未知。
-
@jcy 嘿,时隔这么久。我开始尝试使用 Qt 的地图插件将高德地图进行集成,现在遇到了一些难题。
参考原型是
mapbox
,但是发现这个原型对高德的 web 服务接口并不适合。现在尝试更换到osm
这个插件。如下为运行的效果:
下面是参考资料。
-
@qyvlik 这个好诡异!为什么Qt公司的位置在北京和非洲呢?
是不是我们需要将The Qt Company移除呢?
-
@jcy 由于 Qt 的地图框架使用成熟的瓦片地图。
OpenStreetMap/Google/百度/Bing瓦片地图服务(TMS)
开源与成熟商业的瓦片地图服务(TMS 2 WMTS),都有如下共同的特性,基本成为了标准:
(1) 坐标系:WGS84
(2) 投影:墨卡托投影(Marcator,正轴等角圆柱投影)但是高德地图使用的坐标系是火星坐标系,Qt地图框架会以
WGS84
的瓦片坐标进行请求,在进行换算后,获取到的瓦片地图仍然有很多问题,获取不准确。一下为换算的代码:
static double a = 6378245.0; static double ee = 0.00669342162296594323; static bool outOfChina(double lat, double lon) { if (lon < 72.004 || lon > 137.8347) return true; if (lat < 0.8293 || lat > 55.8271) return true; return false; } static double transformLat(double x, double y) { double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * std::sqrt(std::abs(x)); ret += (20.0 * std::sin(6.0 * x * M_PI) + 20.0 * std::sin(2.0 * x * M_PI)) * 2.0 / 3.0; ret += (20.0 * std::sin(y * M_PI) + 40.0 * std::sin(y / 3.0 * M_PI)) * 2.0 / 3.0; ret += (160.0 * std::sin(y / 12.0 * M_PI) + 320 * std::sin(y * M_PI / 30.0)) * 2.0 / 3.0; return ret; } static double transformLon(double x, double y) { double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * std::sqrt(std::abs(x)); ret += (20.0 * std::sin(6.0 * x * M_PI) + 20.0 * std::sin(2.0 * x * M_PI)) * 2.0 / 3.0; ret += (20.0 * std::sin(x * M_PI) + 40.0 * std::sin(x / 3.0 * M_PI)) * 2.0 / 3.0; ret += (150.0 * std::sin(x / 12.0 * M_PI) + 300.0 * std::sin(x / 30.0 * M_PI)) * 2.0 / 3.0; return ret; } static std::tuple<double, double> wgs84_To_Gcj02(double lat, double lon) { if (outOfChina(lat, lon)) { return std::tuple<double, double>(0, 0); } double dLat = transformLat(lon - 105.0, lat - 35.0); double dLon = transformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * M_PI; double magic = std::sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = std::sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI); dLon = (dLon * 180.0) / (a / sqrtMagic * std::cos(radLat) * M_PI); double mgLat = lat + dLat; double mgLon = lon + dLon; return std::tuple<double, double>(mgLat, mgLon); } // wgs84 static int long2tilex(double lon, int z) { return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z))); } static int lat2tiley(double lat, int z) { return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z))); } static double tilex2long(int x, int z) { return x / pow(2.0, z) * 360.0 - 180; } static double tiley2lat(int y, int z) { double n = M_PI - 2.0 * M_PI * y / pow(2.0, z); return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); }
通过换算代码,获取到瓦片的
x
,y
,z
,然后拼接 url,然后请求这个 url 所指向的图片。QGeoTiledMapReply *QGeoTileFetcherAMap::getTileImage(const QGeoTileSpec &spec) { QNetworkRequest request; /* http://restaM_PI.amap.com/v3/staticmap ?location=116.481485,39.990464 &zoom=10 &size=750*300 &key=ee95e52bf08006f63fd29bcfbcf21df0 */ std::tuple<double, double> gcj02 = wgs84_To_Gcj02(-tiley2lat(spec.y(), spec.zoom()),-tilex2long(spec.x(), spec.y())); qDebug() << -tiley2lat(spec.y(), spec.zoom()) << -tilex2long(spec.x(), spec.y()) << std::get<0>(gcj02) << std::get<1>(gcj02); QString latitude = QString::number(std::get<0>(gcj02)); QString longitude = QString::number(std::get<1>(gcj02)); QUrl url = QUrl(QStringLiteral("http://restaM_PI.amap.com/v3/staticmap") + "?zoom=" + QString::number(spec.zoom()) + "&size=" + QString::number(tileSize.width())+ "*" + QString::number(tileSize.height()) + // "&location=" + QString::number(location.longitude()) +"," + QString::number(location.longitude()) + "&location=" + latitude + "," + longitude + "&key="+key ); }
但是还是无法正确获取到高德的瓦片地图。
-
@qyvlik 我觉得应该有一个高手会这部分,我可以引入他来一同做好这件事儿。
-
-
@taadis 主要还是高德地图还未推出瓦片地图,还没有相关文档。
-
-
查QML MAP问题正好查回论坛,真是缘分。目前不支持百度地图有点麻烦,准备找点webview控件绕过去,期待你们的更新。
-
目前除了百度地图外,高德等其它地图是支持的,不过官方默认的配置是不支持的,需要自己重载里面的部分算法实现,这方面可以参看开源的Qgroundcontrol里面的qtlocaltion模块;
-
隔了这么久,看看这个
QtLocation plugin for Google maps tile API
有人封装了谷歌地图的 API
Bing plugin for QtLocation module
还有bing的。。
QtLocation TomTom plugin
vladest好厉害
-
@qyvlik 这个就是Qt Location中使用谷歌地图的吧。不过不清楚这个会不会在国内无法使用呢?
-
-
@qyvlik 谢谢无私的分享,这些以后在制作地图插件的时候肯定有用的!
-
之前做过离线地图和瓦片获取这块,实现的是Google、bing、腾讯、osm、雅虎之类,原理就是墨卡托结构,网上都有。
建议使用的是qmapcontrl、opmapcontrol、QGIS、qt location实现。
正计划写实现方法博客,但又感觉太low了,应该没人看。。。
对了,附一张图吧。,怎么上传呢,不会,算了。。。