Qt/C++百度地图/高德地图/天地图/腾讯地图/谷歌地图/加载绘图工具栏
一、前言说明
在地图中提供一个绘图工具栏,可以便捷的在地图上添加各种覆盖物,比如折线、多边形、矩形、圆形等,然后可以获取这些覆盖物的路径以及中心点等属性。这里有几个小插曲,比如百度地图gl版本默认不提供这个功能,是通过引入第三方的开源的js文件来实现的。还有个惊喜就是天地图一开始也以为没有这个功能,翻遍了文档才发现提供了militarySymbols这个控件,非常强大,居然提供了几十种形状,而且有各种箭头形状,满足了更多的场景需求,说实话这点还是很惊讶的。
高德地图并没有提供绘图工具栏悬浮条,但是提供了对应的函数处理,所以可以自定义一个工具栏用来处理。腾讯地图一开始也是以为没有,后面才发现有个drawing.DrawingManager控件,添加到地图上,默认顶部居中展示绘图工具栏。
二、功能特点
- 支持多种地图内核,默认采用百度地图,可选高德地图、天地图、腾讯地图、谷歌地图等。
- 同时支持在线地图和离线地图两种模式,离线地图方便在不联网的场景中使用。
- 支持各种地图控件的启用,比如地图导航、地图类型、缩略图、比例尺、全景导航、实时路况、绘图工具、结果面板等。
- 支持多种地图功能的动态启用禁用,比如地图拖曳、键盘操作、滚轮缩放、双击放大、连续缩放、地图测距等。
- 提供众多js函数接口用于交互,参数极其丰富,能够想到的应用场景需求都有。
- 统一的信号槽机制,地图中的结果统一信号发送出去,收到后根据type类型区分。
- 支持地图交互,比如鼠标按下获取对应位置的经纬度。单击标注点弹出对应点的信息。
- 支持添加标注、删除标注、移动标注、清空标注。
- 标注点可以指定图标图片和尺寸,支持gif动图,支持指定以图片中心对齐还是底部中心对齐。可以设置旋转角度,带富文本提示信息。
- 标注点事件支持单击发信号通知和自己弹框显示信息。
- 提供地址转坐标和坐标转地址接口。
- 支持各种图形绘制,包括折线图、多边形、矩形、圆形、弧线等。
- 可显示悬浮的绘图工具栏,直接在地图上划线、标注点、矩形、圆形等。
- 支持各种区域搜索,比如矩形区域、圆形区域,可以按照关键字匹配将搜索结果显示在地图中。
- 可动态添加离线的行政区边界点数据。可以搜索行政区划并获取该区域的边界点数据。数据可以保存到文件以便离线使用。
- 支持点聚合功能,多个小标注点合并到一个大标注点,防止点密集导致交互不友好。
- 可以添加海量点,每个点都可以单击获取对应坐标和信息。
- 所有的覆盖物信息比如标注点、矩形、多边形、折线图等,都可以主动获取对应的信息比如坐标点和路径等。
- 支持路径规划,支持公交路线、自驾路线、步行路线、骑行路线,不同查询支持不同策略,可选最少时间、最少换乘、不走高架等。
- 路径规划结果可以显示在地图中,也可以获取到路径点坐标集合。这个数据可以保存到文件,以便发给机器人或者无人机做导航用来轨迹移动。
- 可以设置不同的地图视图比如街道图、卫星图、混合图。
- 可以设置不同的样式,比如午夜蓝、青草绿等样式风格。
- 可以设置地图的旋转角度和倾斜角度。
- 提供经纬度坐标纠偏转换功能,比如传入的GPS坐标需要转换到百度地图坐标或者高德地图坐标。各种坐标系转换全部离线函数,支持地球坐标系WGS-84、火星坐标系GCJ-02、百度坐标系BD-09之间的互相转换,涵盖了各种地图的坐标系。
- 提供动态轨迹点移动功能,按照给定的经纬度坐标集合平滑移动。
- 同时支持qwidget和qml,支持编译到安卓系统运行。
三、使用说明

四、相关链接
- 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 名称:bin_map.zip
- 国内站点:https://gitee.com/feiyangqingyun
- 国际站点:https://github.com/feiyangqingyun
五、效果图
六、相关代码
void MapObjBaiDu::addDrawingTool()
{if (!(mapControl & MapControl_Drawing)) {return;}//初始化绘图工具栏html << QString(" var styleOptions = getOverlayProperty();");html << QString(" var drawingManager = new BMapLib.DrawingManager(map, {");html << QString(" isOpen:false,");html << QString(" enableDrawingTool:true,");html << QString(" drawingToolOptions:{anchor:BMAP_ANCHOR_TOP_RIGHT, offset:new BMap.Size(100, 5)},");html << QString(" circleOptions:styleOptions, polylineOptions:styleOptions, polygonOptions:styleOptions, rectangleOptions:styleOptions");html << QString(" });");//添加监听事件获取绘制结果html << QString(" drawingManager.addEventListener('overlaycomplete', function(e) {");html << QString(" overlays.push(e.overlay);");html << QString(" receiveData('overlaycomplete');");html << QString(" });");//执行指定的绘制动作html << QString(" function doDraw(type) {");html << QString(" drawingManager.close();");html << QString(" if (type == 'marker') {");html << QString(" drawingManager.setDrawingMode(BMAP_DRAWING_MARKER);");html << QString(" } else if (type == 'polyline') {");html << QString(" drawingManager.setDrawingMode(BMAP_DRAWING_POLYLINE);");html << QString(" } else if (type == 'polygon') {");html << QString(" drawingManager.setDrawingMode(BMAP_DRAWING_POLYGON);");html << QString(" } else if (type == 'rectangle') {");html << QString(" drawingManager.setDrawingMode(BMAP_DRAWING_RECTANGLE);");html << QString(" } else if (type == 'circle') {");html << QString(" drawingManager.setDrawingMode(BMAP_DRAWING_CIRCLE);");html << QString(" }");html << QString(" if (type != 'cancel') {");html << QString(" drawingManager.open();");html << QString(" }");html << QString(" }");
}void MapObjGaoDe::addDrawingTool()
{//初始化鼠标绘制工具/高德没有悬浮的工具栏/需要自己写网页实现html << QString(" var mouseTool;");html << QString(" function initDraw() {");html << QString(" if (mouseTool) {return}");html << QString(" mouseTool = new AMap.MouseTool(map);");html << QString(" mouseTool.on('draw', function(e) {");html << QString(" var overlay = e.obj;");html << QString(" var type = getOverlayType(overlay);");html << QString(" clickEditor(type, overlay);");html << QString(" overlays.push(overlay);");html << QString(" });");html << QString(" }");//执行指定的绘制动作html << QString(" function doDraw(type) {");html << QString(" initDraw();");html << QString(" var styleOptions = {};");html << QString(" //styleOptions = {fillColor:'#ff0000', strokeColor:'#ff0000'};");html << QString(" if (type == 'marker') {");html << QString(" mouseTool.marker({icon:'../mapimage/marker_min.png'});");html << QString(" } else if (type == 'polyline') {");html << QString(" mouseTool.polyline(styleOptions);");html << QString(" } else if (type == 'polygon') {");html << QString(" mouseTool.polygon(styleOptions);");html << QString(" } else if (type == 'rectangle') {");html << QString(" mouseTool.rectangle(styleOptions);");html << QString(" } else if (type == 'circle') {");html << QString(" mouseTool.circle(styleOptions);");html << QString(" } else {");html << QString(" mouseTool.close();");html << QString(" }");html << QString(" }");//识别单击事件切换编辑器html << QString(" function clickEditor(type, overlay) {");html << QString(" overlay.off('click');");html << QString(" overlay.on('click', function(e) {");html << QString(" initEditor(edit ? type : '', e.target);");html << QString(" if (editor) {");html << QString(" editor.open();");html << QString(" }");html << QString(" });");html << QString(" }");//初始化覆盖物对应的编辑对象/高德地图通过编辑器来实现编辑html << QString(" var editor = null;");html << QString(" function initEditor(type, overlay) {");html << QString(" if (editor) {");html << QString(" editor.close();");html << QString(" editor = null;");html << QString(" }");html << QString(" if (type == 'polyline') {");html << QString(" editor = new AMap.%1(map, overlay);").arg(polylineEditor);html << QString(" } else if (type == 'polygon') {");html << QString(" editor = new AMap.%1(map, overlay);").arg(polygonEditor);html << QString(" } else if (type == 'rectangle') {");html << QString(" editor = new AMap.%1(map, overlay);").arg(rectangleEditor);html << QString(" } else if (type == 'circle') {");html << QString(" editor = new AMap.%1(map, overlay);").arg(circleEditor);html << QString(" }");html << QString(" }");//启用禁用编辑html << QString(" var edit = false;");html << QString(" function enableEdit(enable) {");html << QString(" edit = enable;");html << QString(" if (!edit && editor) {");html << QString(" editor.close();");html << QString(" editor = null;");html << QString(" }");//标注点单独设置可拖动/非标注点全部采用编辑对象html << QString(" for (var i = 0; i < overlays.length; ++i) {");html << QString(" var overlay = overlays[i];");html << QString(" if (overlay instanceof AMap.Marker) {");html << QString(" overlay.setDraggable(edit);");html << QString(" }");html << QString(" }");html << QString(" }");
}void MapObjGoogle::addDrawingTool()
{if (!(mapControl & MapControl_Drawing)) {return;}//初始化绘图工具栏html << QString(" var styleOptions = getOverlayProperty();");html << QString(" var drawingManager = new GMap.drawing.DrawingManager({");html << QString(" drawingControl:true,");html << QString(" drawingControlOptions:{position:GMap.ControlPosition.TOP_CENTER},");html << QString(" circleOptions:styleOptions, polylineOptions:styleOptions, polygonOptions:styleOptions, rectangleOptions:styleOptions");html << QString(" });");html << QString(" drawingManager.setMap(map);");//添加监听事件获取绘制结果html << QString(" GMap.event.addListener(drawingManager, 'overlaycomplete', function(e) {");html << QString(" var overlay = e.overlay;");html << QString(" overlay.type = e.type;");html << QString(" overlays.push(overlay);");html << QString(" });");//执行指定的绘制动作html << QString(" function doDraw(type) {");html << QString(" drawingManager.setDrawingMode(null);");html << QString(" if (type == 'marker') {");html << QString(" drawingManager.setDrawingMode(GMap.drawing.OverlayType.MARKER);");html << QString(" } else if (type == 'polyline') {");html << QString(" drawingManager.setDrawingMode(GMap.drawing.OverlayType.POLYLINE);");html << QString(" } else if (type == 'polygon') {");html << QString(" drawingManager.setDrawingMode(GMap.drawing.OverlayType.POLYGON);");html << QString(" } else if (type == 'rectangle') {");html << QString(" drawingManager.setDrawingMode(GMap.drawing.OverlayType.RECTANGLE);");html << QString(" } else if (type == 'circle') {");html << QString(" drawingManager.setDrawingMode(GMap.drawing.OverlayType.CIRCLE);");html << QString(" }");html << QString(" }");
}void MapObjTian::addDrawingTool()
{//执行指定的绘制动作/每次绘制完成都会自动关闭/需要拦截事件重新开启html << QString(" var mouseTool;");html << QString(" function doDraw(type) {");html << QString(" if (mouseTool) {");html << QString(" mouseTool.close();");html << QString(" mouseTool = null;");html << QString(" }");html << QString(" if (type == 'marker') {");html << QString(" mouseTool = new T.MarkTool(map, {follow: true});");html << QString(" mouseTool.addEventListener('mouseup', function(e) {");html << QString(" overlays.push(e.currentMarker);");html << QString(" openDraw();");html << QString(" });");html << QString(" } else if (type == 'polyline') {");html << QString(" mouseTool = new T.PolylineTool(map);");html << QString(" mouseTool.addEventListener('draw', function(e) {");html << QString(" overlays.push(e.currentPolyline);");html << QString(" openDraw();");html << QString(" });");html << QString(" } else if (type == 'polygon') {");html << QString(" mouseTool = new T.PolygonTool(map);");html << QString(" mouseTool.addEventListener('draw', function(e) {");html << QString(" overlays.push(e.currentPolygon);");html << QString(" openDraw();");html << QString(" });");html << QString(" } else if (type == 'rectangle') {");html << QString(" mouseTool = new T.RectangleTool(map);");html << QString(" mouseTool.addEventListener('draw', function(e) {");html << QString(" overlays.push(e.currentRectangle);");html << QString(" openDraw();");html << QString(" });");html << QString(" } else if (type == 'circle') {");html << QString(" mouseTool = new T.CircleTool(map, {follow: true});");html << QString(" mouseTool.addEventListener('drawend', function(e) {");html << QString(" overlays.push(e.currentCircle);");html << QString(" openDraw();");html << QString(" });");html << QString(" }");html << QString(" if (type != 'cancel') {");html << QString(" mouseTool.open();");html << QString(" }");html << QString(" }");//延时打开鼠标绘制工具html << QString(" function openDraw() {");html << QString(" setTimeout(function(){mouseTool.open()}, 100);");html << QString(" }");
}
相关文章:
Qt/C++百度地图/高德地图/天地图/腾讯地图/谷歌地图/加载绘图工具栏
一、前言说明 在地图中提供一个绘图工具栏,可以便捷的在地图上添加各种覆盖物,比如折线、多边形、矩形、圆形等,然后可以获取这些覆盖物的路径以及中心点等属性。这里有几个小插曲,比如百度地图gl版本默认不提供这个功能…...
Vue2 与 Vue3 的区别有哪些
Vue 2 和 Vue 3 在许多方面都有显著的区别,包括性能、API 设计、功能特性等。以下是它们主要的区别: 1. 响应式系统 Vue 2: 基于 Object.defineProperty: Vue 2 使用 Object.defineProperty 来实现响应式数据。这种方法在处理对象属性时有一定的局限性…...
加锁造成的线程优先级反转
优先级反转(Priority Inversion),也称优先级翻转,一般是在优先级不同的多线程环境中发生。在桌面操作系统中,线程的优先级不是太重要,因此较少见优先级反转的现象。但是,优先级反转是实时操作系统(RTOS)中一个常见的问题,特别是在采用优先级调度算法的系统中。这个问…...
【日常记录-Java】SpringBoot中使用无返回值的异步方法
Author:赵志乾 Date:2024-09-05 Declaration:All Right Reserved!!! 1. 简介 在SpringBoot中,使用Async注解可以很方便地标记一个方法为异步执行。好处是调用者无需等待这些方法完成便可继续执…...
【深度学习】多层感知机的从零开始实现与简洁实现
可以说,到现在我们才真正接触到深度网络。最简单的深度网络称为多层感知机。 多层感知机由多层神经元组成,每一层与它的上一层相连,从中接收输入;同时每一层也与它的下一层相连,影响当前层的神经元。 和以前相同&…...
4、Django Admin对自定义的计算字段进行排序
通常,Django会为模型属性字段,自动添加排序功能。当你添加计算字段时,Django不知道如何执行order_by,因此它不会在该字段上添加排序功能。 如果要在计算字段上添加排序,则必须告诉Django需要排序的内容。你可以通过在…...
rsync搭建全网备份
rsync搭建全网备份 1. 总体概述1.1 目标1.2 简易指导图1.3 涉及工具或命令1.4 环境 2. 实施2.1 配置备份服务器2.2 备份文件准备2.3 整合命令2.4 扩展功能 1. 总体概述 1.1 目标 本次搭建目标: 每天定时把服务器数据备份到备份服务器备份完成后进行校验把过期数据…...
网络安全售前入门09安全服务——安全加固服务
目录 1.服务概述 2.流程及工具 2.1服务流程 2.2服务工具 3.服务内容 4.服务方式 5.风险规避措施 6.服务输出 1.服务概述 安全加固服务是参照风险评估、等保测评、安全检查等工作的结果,基于科学的安全思维方式、长期的安全…...
【Android】GreenDao数据库的使用方式
需求 使用GreenDao数据库进行数据的存储。 介绍 GreenDao 是一个轻量级的对象关系映射(ORM)库,用于简化 Android 应用中的数据库操作。它提供了以下主要功能: 简化数据库操作:通过注解定义实体类,Green…...
搜索算法之线性搜索详细解读(附带Java代码解读)
1. 基本概念 线性搜索(Linear Search),也称为顺序搜索,是一种在列表中查找特定元素的算法。它从列表的第一个元素开始,逐个检查每个元素,直到找到目标元素或检查完所有元素。 2. 工作原理 线性搜索的操作…...
Quartz.Net_依赖注入
简述 有时会遇到需要在IJob实现类中依赖注入其他类或接口的情况,但Quartz的默认JobFactory并不能识别具有有参构造函数的IJob实现类,也就无法进行依赖注入 需要被依赖注入的类: public class TestClass {public TestClass(Type jobType, s…...
【系统架构设计师-2011年】综合知识-答案及详解
更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【第1题】【第2~4题】【第5~7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18~19题】【第20~21题】【第22题】【第23题】【第24题】【第25题】【第2…...
World of Warcraft [CLASSIC][80][Grandel]Sapphire Hive Drone
Sapphire Hive Drone 蓝玉虫巢雄蜂 蓝玉虫巢巨峰 索拉查盆地 实用性不强,好看是好看,模型很大,无奈栏位太少...
Unity 对接 Android 第三方广告,App 切换到后台后,再次打开时,第三方广告被销毁导致无法触发回调逻辑的问题
该问题是由发行进行游戏测试时遇到并反馈的。大致情况如下: 1. 当触发了插屏广告后,在关闭广告前将 App 切换到后台,之后再次打开 App,此时插屏广告消失,并切游戏卡死。 2. 当触发激励视频广告后,在广告展…...
Kafka Broker处于高负载状态(例如消息处理量大或系统资源不足),无法及时响应消费者的请求
Caused by: org.apache.kafka.common.errors.TimeoutException: Timeout of 60000ms expired before the position for partition activity-0 could be determined。 出现这个错误的原因是Kafka消费者在尝试获取分区(activity-0)的位置信息时,超时了。在60秒内无法确…...
相关二叉树进阶面试题的讲解?看这一篇足矣
引子:我们在之前学过c语言的二叉树,但是c来做更好!本期要讲的题目如下(其实有点拖欠了,很久之前,就想写这个了,今天终于克服自己的欲望,达成了这个愿望) 1, 二叉树创建字…...
Nginx部署前端Vue项目的深度解析
目录 一、准备工作 1.1 开发环境 1.2 服务器环境 1.3 Nginx安装 二、构建Vue项目 三、上传静态文件到服务器 四、配置Nginx 五、测试并重新加载Nginx 六、访问Vue应用 七、高级配置 7.1 启用HTTPS 7.2 启用Gzip压缩 7.3 缓存控制 八、常见问题与解决方案 8.1 40…...
PHP一站式解决方案高级房产系统小程序源码
一站式解决方案,高级房产系统让房产管理更轻松 🏠【开篇:告别繁琐,迎接高效房产管理新时代】🏠 你是否还在为房产管理的繁琐流程而头疼?从房源录入、客户咨询到合同签订、售后服务,每一个环节…...
轻量级模型解读——EfficientNet系列
EfficientNet自2019年谷歌提出以来,经历了三个版本,2019EfficientNet ——> 2020EfficientNet-Lite——> 2021EfficientNetv2 文章目录 1、EfficientNet2、EfficientNetv23、EfficientNet-Lite 对于EfficientNet和EfficientNetv2的解读可见另外两篇…...
深入浅出SRS—RTMP实现
RTMP 直播是 SRS 最典型的使用场景,客户端使用 RTMP 协议向 SRS 推流,使用 RTMP 协议从 SRS 拉流,SRS 作为一个 RTMP 直播服务器实现媒体的转发。同时,RTMP 是 SRS 的中转协议,其他协议之间的互通需要先转为 RTMP&…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
