QML Map中测距

  • 1. 实现思路
  • 2. 实现代码及git链接

本文转载于:QML QtLocation轻量级地图应用学习:实现测距功能


所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多的时间吧!

QML其它文章请点击这里:     QT QUICK QML 学习笔记


1. 实现思路

参照百度or高德地图的测距功能,主要由两种元素组成,标记点和连线。

其中连线很好解决,Qt 提供了 MapPolyline 类型,可以用来绘制折线,并且提供了增删的便捷函数:

对于标记点,我们可以用 MapQuickItem 来实现,里面包含一个标记圆圈、长度Text、删除按钮。对于一组 MapQuickItem,我使用 MapItemView 来管理。而求两个坐标点的距离,直接调用的 coordinate 类型的 distanceTo 函数,总长直接遍历求距离就行了。

接下来就是封装一个 Ruler 的组件,实现多次测距的绘制。每次开始测距时,通过 createObject 动态创建一个 Ruler 组件,然后往里面添加坐标点。坐标点我是在 Map 上放了一个 MouseArea ,然后用 Map 的 toCoordinate 方法把 point 转换成坐标点。

此外,如果要自己计算两点距离,可以参考网上球面两点距离的公式,如:


上面参考的表示法应该是十进制的,如果是度分秒的形式,可以先转化下:

2. 实现代码及git链接

下面是实现效果:

有一点还没解决,那就是 MapPolyline 这种图元设置 layer 实现平滑效果的话,放大之后很卡。另外就是,一个 Ruler 所有元素被删之后我也没有析构它。

Ruler组件的实现代码:

//MapRuler.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12// 一次测距里包含多个标记点以及连线
MapItemGroup{id: controlMapPolyline {id: item_lineline.color: "red"line.width: 2//平滑后放大有点卡//layer.enabled: true//layer.smooth: true//layer.samples: 8function getDistanceCount(){var distance_count=0;for(var i=1;i<pathLength();i++){distance_count+=item_line.coordinateAt(i).distanceTo(item_line.coordinateAt(i-1));}return Math.round(distance_count);}}MapItemView{id: item_viewadd: Transition {}remove: Transition {}model: ListModel{id: item_model}delegate: MapQuickItem{id: ietm_delegatesourceItem: Rectangle {width: 14height: 14radius: 7color: "white"border.width: 2border.color: "red"Rectangle{anchors.left: parent.rightanchors.top: parent.bottomwidth: item_text.width+5+5+14+5height: item_text.height+10border.color: "gray"Text {id: item_textx: 5anchors.verticalCenter: parent.verticalCentertext: index<=0? "起点": (index==item_model.count-1)? ("总长 "+item_line.getDistanceCount()/1000+" km"):(Math.round(ietm_delegate.coordinate.distanceTo(item_line.coordinateAt(index-1)))/1000+" km")}Rectangle{width: 14height: 14anchors.right: parent.rightanchors.rightMargin: 5anchors.verticalCenter: parent.verticalCenterborder.color: "red"Text {color: "red"anchors.centerIn: parenttext: "+"rotation: 45}MouseArea{anchors.fill: parentonClicked: {//最后一个全部删除,否则一个一个的删除//为0的时候发送信号给group请求删除if(index==item_model.count-1){item_line.path=[];item_model.clear();//control.destroy();}else{item_line.removeCoordinate(index);item_model.remove(index);}}}}}//Component.onDestruction: console.log("destory item");}//通过listmodel来设置数据coordinate{latitude: latitudevallongitude: longitudeval}anchorPoint: Qt.point(sourceItem.width/2, sourceItem.height/2)}}function appendPoint(coord){//var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);//console.log("area",coord.latitude,coord.longitude);item_model.append({"latitudeval":coord.latitude,"longitudeval":coord.longitude});item_line.addCoordinate(coord);//mouse_area._closePath=false;//console.log("ruler append",item_model.count,item_line.pathLength())}function followMouse(coord){if(item_line.pathLength()<=0)return;if(item_line.pathLength()===item_model.count){item_line.addCoordinate(coord);}else{item_line.replaceCoordinate(item_line.pathLength()-1,coord);}}function closePath(){while(item_line.pathLength()>item_model.count){item_line.removeCoordinate(item_line.pathLength()-1);}}
}

在 Window 中调用下面组件来展示 Demo:

 //Demo.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12//地图自定义
Item{id: control//地图的模式// 0:普通浏览// 1:测距property int mapMode: 0property MapRuler currentRuler: nullproperty alias map: the_mapclip: trueonMapModeChanged: {console.log("map mode",mapMode);if(control.mapMode!=1&&currentRuler){currentRuler.closePath();currentRuler=null;}}//缩放等级,维度,精度function viewPoint(zoomLevel,latitude,longitude){the_map.zoomLevel=zoomLevel;the_map.center=QtPositioning.coordinate(latitude, longitude);}Row{RadioButton{text: "Normal"checked: trueonCheckedChanged: if(checked)control.mapMode=0;}RadioButton{text: "Ruler"onCheckedChanged: if(checked)control.mapMode=1;}}Map {id: the_mapanchors.fill: parentanchors.topMargin: 40minimumZoomLevel: 4maximumZoomLevel: 16zoomLevel: 10center: QtPositioning.coordinate(30.6562, 104.0657)plugin: Plugin {name: "esri" //"esri" "mapbox" "osm" "here"}//显示缩放等级与centerRectangle{anchors{left: the_map.leftbottom: the_map.bottommargins: 5}width: content.width+20height: content.height+10Text {id: contentx: 10y: 5font.pixelSize: 14text: "Zoom Level "+Math.floor(the_map.zoomLevel)+" Center:"+the_map.center.latitude+"  "+the_map.center.longitude}}MouseArea{id: map_mouseanchors.fill: parentenabled: control.mapMode!=0//画了一个点后跟随鼠标,除非双击hoverEnabled: trueonClicked: {// 1 测距if(control.mapMode===1){if(!currentRuler){currentRuler=ruler_comp.createObject(the_map);if(currentRuler)the_map.addMapItemGroup(currentRuler);}if(currentRuler){var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);currentRuler.appendPoint(coord);}}}onDoubleClicked: {// 1 测距if(control.mapMode===1){if(currentRuler){currentRuler.closePath();currentRuler=null;}}}onPositionChanged: {// 1 测距if(control.mapMode===1){if(currentRuler){var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);currentRuler.followMouse(coord);}}}}}Component{id: ruler_compMapRuler{}}
}

代码 github 链接:https://github.com/gongjianbo/MyQtLocation

QML Map中测距——QtLocation轻量级地图应用学习相关推荐

  1. QML QtLocation地图应用学习-1:在Map中展示图元 Item

    目录 0.前言 1.开始 2.在Map中展示图元 3.一个完整的例子 4.Bug:当其他控件具有焦点时,地图上有灰白色方块 0.前言 Qt Location模块可用于轻量级的地图应用开发,不过官方示例 ...

  2. QML 地图修改插件源码(三),Map在Plugin中设置加载地图类型

    常用的地图种类分为交通图,地形图,卫星图等等,在QML的Map(以OSM地图为例)中提供activeMapType属性用于读取当前显示的地图类型(注意:该属性为只读属性,不能用于赋值),QML中地图的 ...

  3. QML地图Map中使用QPainterPath,并显示任意点经纬度位置

    QML地图Map中提供了供绘制图形的组件,例如MapPolyline,MapCircle等,但是这些组件在绘制复杂轨迹时就显得功能不够全面,因此我将QPainterPath在Map中进行使用并进行绘制 ...

  4. Qt中使用诺基亚HERE地图的方式

    概述 首先,Qt支持多种地图插件,包括osm,here等等,要看具体支持情况.Qt中使用地图是通过地图类加上地图插件类一起使用的,地图插件的支持情况需要看具体的文档.本文档主要描述如何使用HERE插件 ...

  5. map中批量图层的加载和展示

    private function configopLayermaps():void {var i:int = 0;var len_configData_opLayers:int=configData. ...

  6. vue中使用百度地图为啥是空白_vue中使用腾讯地图(尝试篇)

    引入 在index.html文件中引入腾讯地图js文件,XXX为你申请的key 注意事项:为显示地图的元素设置宽高 单个标注点 js: 在mounted生命周期或者从后台接口获得信息后调用初始化地图方 ...

  7. 在Arcmap中加载互联网地图资源的4种方法

    在Arcmap中加载互联网地图资源的4种方法 前一段时间想在Arcmap中打开互联网地图中的地图数据,如影像数据.基础地图数据等,经过简单研究目前总结了四种方法,整理下与大家分享,有些内容可能理解有误 ...

  8. scala中map添加值_如何在Scala Map中反转键和值

    scala中map添加值 A Map is a data structure that stores data as key: value pair. 映射是一种将数据存储为键:值对的数据结构. Sy ...

  9. map.addoverlay php,覆盖物 - 百度地图开发文档 - php中文网手册

    地图覆盖物概述 所有叠加或覆盖到地图的内容,我们统称为地图覆盖物.如标注.矢量图形元素(包括:折线和多边形和圆).信息窗口等.覆盖物拥有自己的地理坐标,当您拖动或缩放地图时,它们会相应的移动. 地图A ...

最新文章

  1. Windows Azure Platform Introduction (6) Windows Azure应用程序运行环境
  2. 基于存储过程的可扩展性数据访问框架
  3. OpenCV Harris角点检测
  4. 每天一个linxu命令6之jps  查看java进程的端口
  5. 【转】MFC与.NET的区别
  6. java启动器在bin目录_org.iipg.starter
  7. 我们看到一些知乎大V,开始拍视频了
  8. spark 为什么总是起200个task
  9. 经典调用共享变量wait()方法的实例
  10. 【ACM】nyoj_2_括号配对问题_201308091548
  11. 特殊的网络环境下的故障处理
  12. 链表的相关面试题(完整)(C语言)
  13. Iptables 指南 1.1.19
  14. 手游最佳搭档:高续航音质卓越,高颜值精品蓝牙耳机推荐
  15. 行人重识别论文阅读11-BDTR 红外光行人重识别
  16. Linux-Ubuntu 和 安装 genymotion 的一些问题和一些命令
  17. 分享5个常用的CMD命令。
  18. 50_00_000java,时间格式转换2020-04-09T23:00:00.000+08:00
  19. 《机器学习实战》源码和数据集的下载
  20. (实验37)单片机,STM32F4学习笔记,代码讲解【内存管理实验】【正点原子】【原创】

热门文章

  1. 语义计算_语义多态性如何在量子计算中起作用
  2. mysql 命令行修改密码
  3. securecrt修改服务器密码,securecrt怎么修改密码
  4. arcgis 图层概念
  5. Maven –如何跳过单元测试
  6. 随机函数rand()[c++]
  7. BASH文件操作备忘
  8. “顶流”长沙,如何发展MCN?
  9. 经典网络架构学习-ResNet
  10. Shell脚本导出导入MySQL建表语句