有关 QML QtLocation 的 Plugin 的使用问题



  • @jcy 其他的,例如 here 还有 mapbox 要设置 appid 和密钥。


  • 网站研运

    @qyvlik here是商业的,好像现在我们访问不了吧,被收购了。访问http://heremaps.cn,直接跳转了,没办法打开地图。mapbox未知。



  • @jcy 嘿,时隔这么久。我开始尝试使用 Qt 的地图插件将高德地图进行集成,现在遇到了一些难题。

    参考原型是 mapbox,但是发现这个原型对高德的 web 服务接口并不适合。现在尝试更换到 osm 这个插件。

    如下为运行的效果:

    0_1464873914645_U~G7)BP_1HIF0407S{TR0)B.png

    0_14648739g

    下面是参考资料。

    Slippy map tilenames(瓦片和经纬度换算)

    由经纬度计算Google卫星地图中瓦片Tile的地址

    百度与谷歌地图瓦片组织方式对比 (修正)!


  • 网站研运

    @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)));
    }
    

    通过换算代码,获取到瓦片的xyz,然后拼接 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 我觉得应该有一个高手会这部分,我可以引入他来一同做好这件事儿。



  • @qyvlik 坐标系不同导致的问题,可以看看这个有无帮助,
    起码转换后的坐标是匹配的坐标转换



  • @taadis 主要还是高德地图还未推出瓦片地图,还没有相关文档。





  • 查QML MAP问题正好查回论坛,真是缘分。目前不支持百度地图有点麻烦,准备找点webview控件绕过去,期待你们的更新。



  • 目前除了百度地图外,高德等其它地图是支持的,不过官方默认的配置是不支持的,需要自己重载里面的部分算法实现,这方面可以参看开源的Qgroundcontrol里面的qtlocaltion模块;



  • 隔了这么久,看看这个

    vladest/googlemaps

    QtLocation plugin for Google maps tile API

    有人封装了谷歌地图的 API

    vladest/Bing

    Bing plugin for QtLocation module

    还有bing的。。

    vladest/TomTom

    QtLocation TomTom plugin

    vladest好厉害



  • @qyvlik 这个就是Qt Location中使用谷歌地图的吧。不过不清楚这个会不会在国内无法使用呢?



  • 国内的百度地图,腾讯地图的瓦片接口,现在只找到一些支离破碎的信息

    搜搜地图服务示例

    以及这个~

    腾讯与百度地图瓦片规则分析



  • @qyvlik 谢谢无私的分享,这些以后在制作地图插件的时候肯定有用的!



  • 之前做过离线地图和瓦片获取这块,实现的是Google、bing、腾讯、osm、雅虎之类,原理就是墨卡托结构,网上都有。
    建议使用的是qmapcontrl、opmapcontrol、QGIS、qt location实现。
    正计划写实现方法博客,但又感觉太low了,应该没人看。。。
    对了,附一张图吧。![alt text](image url),怎么上传呢,不会,算了。。。



  • @欢快的基佬 写啊!我要高德的!我支持~



  • @qyvlik有关 QML QtLocation 的 Plugin 的使用问题 中说:

    @欢快的基佬 写啊!我要高德的!我支持~

    怎么传图片、、、、



  • @欢快的基佬 使用markdown的语法,或者就像QQ那样,复制图片,然后在这个输入框粘贴图片。

    0_1490714783359_upload-d114ed6a-53c5-4850-a781-f76df95d054f



  • @qyvlik 好的。。
    首先看一下做好的离线地图预览,包含Google、Bing、腾讯、雅虎、以及一票QML MAP自带的那些插件。
    下面是腾讯地图的离线版。
    0_1490926199651_upload-4b5f79f2-13b2-495c-885d-42c6087a1f76
    是不是和在线的一毛一样(这是肯定的啊、、)。
    地图主要分为街道、地形(鸟瞰)、混合三大种,在Qt 5.5以后的版本QGeoMapType类中有定义。
    (帮助手册中可能没有,在插件QtLocation下,可以看到源码)

    小伙伴们要区分瓦片和静态图啊,API拉下的是静态图,拼接偏移就不说了,还自带logo。。
    瓦片是你用浏览器浏览时,在线地图加载的图元,可以随便打开个地图,比如谷歌地图,按F12,在开发工具中可以看到。(sources>source>map)
    0_1490926802649_upload-93a0f8b2-1ac1-40f2-b206-25f1ca09a084
    里面加载了众多图元,图元的连接像这样:(可以打开看看)
    https://www.google.com/maps/vt/pb=!1m4!1m3!1i4!2i3!3i4!2m3!1e0!2sm!3i377063396!3m7!2szh-CN!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0!5m1!1e0
    这些图元就是瓦片,我们要模拟浏览器行为,获取到这些瓦片,再储存起来,就做成了离线地图。


Log in to reply
 

走马观花

最近的回复

  • 这张图或许阐述了这个问题。
    有效打造个人品牌.png

    其实对于我们职场人员,尤其是程序员,都有很强的作用。我们虽然产品意识比较弱,但是我们对产品的敏感性强,尤其是我们有制作过产品的经验,这反而是一个优势。

    read more
  • @jiangcaiyang 给你一个大大的赞!
    论坛最近打算再次启用iframely服务了。试试看!

    https://community.nodebb.org/topic/4401

    read more

关注我们

微博
QQ群