添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

参照网上的测面积功能,界面效果和测距差不多,在点和线的基础上多了一个填充区域。

点和线参照上一篇博客: https://blog.csdn.net/gongjianbo1992/article/details/103674047

填充区域使用 MapPolygon ,但是这个类接口很少,大部分操作还是借住折线 MapPolyline 来完成。

这个功能最主要的是根据坐标点的集合求面积,在网上找了很多参考代码,大部分思路是球面多边形面积计算,但是计算结果都不一样,有误差。

最后我用的是别人从高德的API里提取出来的函数。下面给出部分参考链接:

JS实现(首尾太近会算错): https://blog.csdn.net/neil89/article/details/49331641

Py实现: https://www.cnblogs.com/c-w20140301/p/10308431.html

Java参照的高德API: https://blog.csdn.net/zdb1314/article/details/80661602

根据球面面积计算公式: https://wenku.baidu.com/view/4e213e27162ded630b1c59eef8c75fbfc67d94e2.html

2.实现代码及git链接

下面是实现效果:

Area组件实现代码:

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12
// 计算地图连线围成面积
MapItemGroup{
    id: control
    property bool _pathClose: false
    property double areaValue: 0
    //MapPolygon很多方法没有,所以拿MapPolyline来记录坐标点
    //优化的话自定义cpp类型
    MapPolygon{
        id: item_polygon
        color: Qt.rgba(0,1,0,0.4);
        border.width: 0
        path: item_line.path
    MapPolyline{
        id: item_line
        line.width: 1
        line.color: "red"
    MapItemView{
        id: item_view
        add: Transition {}
        remove: Transition {}
        model: ListModel{
            id: item_model
        delegate: MapQuickItem{
            id: ietm_delegate
            sourceItem: Rectangle {
                width: 14
                height: 14
                radius: 7
                color: "white"
                border.width: 2
                border.color: "red"
                //Component.onDestruction: console.log("destory item");
                Loader{
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.top: parent.bottom
                    anchors.margins: 5
                    sourceComponent: (_pathClose&&index==(item_model.count-1))?area_comp:null_comp
            //通过listmodel来设置数据
            coordinate{
                latitude: latitudeval
                longitude: longitudeval
            anchorPoint: Qt.point(sourceItem.width/2, sourceItem.height/2)
    Component{
        id: null_comp
        Item{}
    Component{
        id: area_comp
        Rectangle{
            width: area_text.width+5+5+14+5
            height: area_text.height+10
            border.color: "gray"
            Text {
                id: area_text
                anchors.verticalCenter: parent.verticalCenter
                text: control.areaValue+" m^2"
            Rectangle{
                width: 14
                height: 14
                anchors.right: parent.right
                anchors.rightMargin: 5
                anchors.verticalCenter: parent.verticalCenter
                border.color: "red"
                Text {
                    color: "red"
                    anchors.centerIn: parent
                    text: "+"
                    rotation: 45
                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        clearPath();
    function appendPoint(coord){
        item_model.append({"latitudeval":coord.latitude,"longitudeval":coord.longitude});
        item_line.addCoordinate(coord);
    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(){
        control._pathClose=true;
        while(item_line.pathLength()>item_model.count){
            item_line.removeCoordinate(item_line.pathLength()-1);
        if(item_line.pathLength()<3){
            clearPath();
            return;
        control.areaValue=getPolygonArea(item_line.path);
        item_line.addCoordinate(item_line.path[0]);
    function clearPath(){
        item_line.path=[];
        item_model.clear();
    //计算方式1:https://www.cnblogs.com/c-w20140301/p/10308431.html
    //根据py代码换砖而来
    //转换为弧度
    function convertToRadian(num){
        return num*Math.PI/180;
    //计算地图区域面积
    function calculatePolygonArea(path){
        let area_count=0;
        let path_len=path.length;
        if(path_len<3)
            return area_count;
        let data_list=[];
        for(let i=0;i<path_len;i++){
            area_count+=convertToRadian(path[(i+1)%path_len].longitude-path[(i)%path_len].longitude)*
                    (2+Math.sin(convertToRadian(path[(i)%path_len].latitude))+
                     Math.sin(convertToRadian(path[(i+1)%path_len].latitude)));
        area_count*=6378137.0 * 6378137.0 / 2.0;
        return Math.abs(area_count);
    //计算方式2:https://blog.csdn.net/zdb1314/article/details/80661602
    //应该是提取的高德api里的函数,命名应该是混淆加密之后的
    function getPolygonArea(path){
        let area_count=0;
        let path_len=path.length;
        if(path_len<3)
            return area_count;
        let data_list=[];
        //WGS84地球半径
        let sJ = 6378137;
        //Math.PI/180
        let Hq = 0.017453292519943295;
        let c = sJ *Hq;
        for(let i=0;i<path_len-1;i++){
            let h=path[i];
            let k=path[i+1];
            let u=h.longitude*c*Math.cos(h.latitude*Hq);
            let hhh=h.latitude*c;
            let v=k.longitude*c*Math.cos(k.latitude*Hq);
            area_count+=(u*k.latitude*c-v*hhh);
        let eee=path[path_len-1].longitude*c*Math.cos(path[path_len-1].latitude*Hq);
        let g2=path[path_len-1].latitude*c;
        let k=path[0].longitude*c*Math.cos(path[0].latitude*Hq);
        area_count+=eee*path[0].latitude*c-k*g2;
        return Math.round(Math.abs(area_count)/2);

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

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12
//地图自定义
Item{
    id: control
    //地图的模式
    // 0:普通浏览
    // 1:测距
    // 2:截图
    // 3:面积
    property int mapMode: 0
    property MapArea currentArea: null
    property alias map: the_map
    clip: true
    onMapModeChanged: {
        console.log("map mode",mapMode);
        if(control.mapMode!=3&&currentArea){
            currentArea.closePath();
            currentArea=null;
    //缩放等级,维度,精度
    function viewPoint(zoomLevel,latitude,longitude){
        the_map.zoomLevel=zoomLevel;
        the_map.center=QtPositioning.coordinate(latitude, longitude);
        RadioButton{
            text: "Normal"
            checked: true
            onCheckedChanged: if(checked)control.mapMode=0;
        RadioButton{
            text: "Area"
            onCheckedChanged: if(checked)control.mapMode=3;
    Map {
        id: the_map
        anchors.fill: parent
        anchors.topMargin: 40
        minimumZoomLevel: 4
        maximumZoomLevel: 16
        zoomLevel: 10
        center: QtPositioning.coordinate(30.6562, 104.0657)
        plugin: Plugin { //这里使用了自定义plugin请忽略
            name: "mymap" //"esri" "mapbox" "osm" "here"
            PluginParameter {
                name: "baseUrl"
                // 自行指定瓦片路径
                value: "file:///"+applicationDirPath+"/dianzi_gaode_ArcgisServerTiles/_alllayers"
            PluginParameter {
                name: "format"
                value: "png"
        //显示缩放等级与center
        Rectangle{
            anchors{
                left: the_map.left
                bottom: the_map.bottom
                margins: 5
            width: content.width+20
            height: content.height+10
            Text {
                id: content
                x: 10
                font.pixelSize: 14
                text: "Zoom Level "+Math.floor(the_map.zoomLevel)+" Center:"+the_map.center.latitude+"  "+the_map.center.longitude
        MouseArea{
            id: map_mouse
            anchors.fill: parent
            enabled: control.mapMode!=0
            //画了一个点后跟随鼠标,除非双击
            hoverEnabled: true
            onClicked: {
                // 3 面积
                if(control.mapMode===3){
                    if(!currentArea){
                        currentArea=area_comp.createObject(the_map);
                        if(currentArea)
                            the_map.addMapItemGroup(currentArea);
                    if(currentArea){
                        var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);
                        currentArea.appendPoint(coord);
            onDoubleClicked: {
                // 3 面积
                if(control.mapMode===3){
                    if(currentArea){
                        currentArea.closePath();
                        currentArea=null;
            onPositionChanged: {
                // 3 面积
                if(control.mapMode===3){
                    if(currentArea){
                        var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);
                        currentArea.followMouse(coord);
    Component{
        id: area_comp
        MapArea{

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

1.实现思路参照网上的测面积功能,界面效果和测距差不多,在点和线的基础上多了一个填充区域。点和线参照上一篇博客:https://blog.csdn.net/gongjianbo1992/article/details/103674047填充区域使用MapPolygon ,但是这个类接口很少,大部分操作还是借住折线MapPolyline 来完成。这个功能最主要的是根据坐标点的... Qt从C++的图形界面库这种小角色,已经逐渐发展为类似于.NET这种平台化的类库了,近年来又推出了QQuick框架,推陈出新得很快,加之本身的跨平台特性,似乎成了C++做图形应用程序的首选。于是,我也赶潮流速成了一下,主要是搞一个电子地图的解决方案。 Qt本身是面向对象的,其核...
1.实现思路 行政区划是一个常见的地图功能,我们需要给不同的区域绘制轮廓。如果使用百度或高德的网页在线地图进行开发,那么直接就可以查询到一个区域的边界点(高德比百度更密集点),之后就可以绘制这个区域了。 参见百度Demo:http://lbsyun.baidu.com/jsdemo.htm#c1_10) 百度的接口是这样获取区域边界的: 我们可以把需要的区域输入进去,然后把点打印出...
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录前言一、分析Qt location 源码中 esri模块源码二、创建自己的插件,显示天地图1.创建工程2.开始修改代码总结 本章节讲如何制作自己的地图插件,我们以制作天地图插件为例,做一个简单的天地图插件,当然也可以做google,bing,高德,百度等,思路都一样 文档如是说,QML旨在通过C ++代码轻松扩展。Qt QML模块中的类使QML对象能够从C ++加载和操作,QML引擎与Qt元对象系统集成的本质使得C ++功能可以直接从QML调用。这允许开发混合应用程序,这些应用程序是通过混合使用QML,JavaScript和C ++代码实现的。 QML is designed to be easily extensible through C++ c... 1.写在前面 在Qt5.12中,QtQuick 2 添加了 TableView 组件,功能和 QtQuickControl 1 中的 TableView 类似,但是接口大不一样(QtQuick Control 1已经处于弃用状态,不建议使用)。 Qt Creator中有两个 QtQuick 2 TableView 的示例,但是都不是数据类型的,参考起来不大方... 信号和槽(signals &amp; slots)是Qt框架的核心机制,Qt C++中的槽函数对应QML中的信号处理程序(signal handler)。 信号是事件(event),信号通过信号处理程序响应。发出信号时,将调用相应的信号处理程序。在处理程序中放置诸如脚本或其他操作之类的逻辑允许组件响应事件。 第一个例子:信号处理程序 //以下所有示例都在Qt5.9.7下测试 imp...
你好!对于学习QtLocation地图应用,我可以为你提供一些指导。首先,QtLocation是Qt框架中的一个模块,用于集成地图和位置服务功能。它提供了一组API和工具,使开发者能够在他们的应用程序中使用地图功能。 要开始学习QtLocation地图应用,你可以按照以下步骤进行: 1. 安装Qt:首先,确保你已经安装了Qt开发环境。你可以从Qt官方网站下载并安装Qt Creator和Qt框架。 2. 导入QtLocation模块:在Qt Creator中创建一个新的Qt项目,并在项目设置中添加QtLocation模块。这将确保你可以使用该模块的功能。 3. 获取地图提供商的API密钥:大多数地图提供商(如Google Maps、Mapbox等)需要API密钥才能使用他们的服务。注册一个开发人员账户并获取API密钥。 4. 配置地图提供商:在代码中设置地图提供商和API密钥。根据你选择的地图提供商和Qt版本,具体的设置方法会有所不同。你可以查阅QtLocation的文档和示例代码来了解如何配置。 5. 在应用程序中添加地图功能:使用QtLocation提供的API,你可以添加地图、标记点、路径等功能到你的应用程序中。可以通过创建QML文件或者使用C++代码来实现。 6. 处理位置信息:QtLocation还提供了一些API来处理设备的位置信息。你可以使用这些API获取设备的当前位置、监听位置变化等。 7. 运行和调试:完成代码编写后,你可以在Qt Creator中运行和调试你的应用程序。确保你的API密钥正确配置,并能够正常显示地图。 以上是一个简单的学习QtLocation地图应用的步骤。当然,在实际开发中可能会涉及到更多的细节和特定需求。我建议你查阅QtLocation的官方文档、示例代码和教程,以便更全面地学习和理解相关知识。祝你学习愉快!
没有MultipartFormDataProvider的定义呢??、 error: no member named 'MultipartFormDataProvider' in namespace 'httplib' httplib::MultipartFormDataProvider; Qt Quick 3D学习:模型加载 qq_41949066: qtquickitem,自定义类封装进item注册调用,链接渲染信号可以有 QML中的附加属性 极端浪漫主义分子: 请问先生什么是静态全局缓存啊,是一个类里面的静态成员吗? QML用ListView实现带section的GridView Jacy-king: 建波建波(破音)