QT realizes the conversion of longitude and latitude into picture pixel coordinates

QT realizes the conversion of longitude and latitude into picture pixel coordinates

Statement of needs

Recently encountered this kind of demand in the development, given the longitude and latitude of the earth, mark the position of the longitude and latitude in a static picture map

demand analysis

The latitude and longitude of the earth is a spherical coordinate system. The picture is a plane coordinate system and cannot be directly converted. Google Maps uses the "Mercator projection method" when converting a spherical surface to a plane. (Interested students can go to Baidu). After the conversion, the longitude is in the plane. The coordinate system is still evenly distributed, while the dimensions are not uniformly distributed. Special calculations are required to obtain the pixel coordinates in the plane coordinate system.

Code

World map example

Take the world map as an example. The largest world map is captured on Google Maps: longitude -180 degrees to 180 degrees, latitude -85 degrees to 85 degrees (the largest latitude of the earth is -90 to 90, after Mercator projection, 90 degrees will tend to At infinity, the plane cannot be represented), the core of the algorithm is to convert the non-uniform dimension into a uniform representation.
widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPainter>
#include <QImage>
namespace Ui {
    
    
class Widget;
}
struct MAP_X_Y{
    
    
    double x;
    double y;
};
class Widget : public QWidget
{
    
    
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    void displayPos();//地图显示位置
    MAP_X_Y AxesConvert(double lon,double lat);//经纬度转换为像素坐标
public slots:
    void slotpushButton();
private:
    Ui::Widget *ui;
    QImage *m_pImage;//定义QImage绘图设备
    QPainter *m_pPainter;//定义画家
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QDebug>
#include <QPainter>
#include <QImage>
#include <cmath>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    
    
    ui->setupUi(this);
    this->setWindowTitle("世界地图");
    m_pImage = new QImage(1024,1024,QImage::Format_ARGB32);
    m_pPainter = new QPainter(m_pImage);

    m_pPainter->drawImage(0,0,QImage("./images/worldMap.jpg"));
    ui->label->setPixmap(QPixmap::fromImage(*m_pImage));//UI控件显示图片
    connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(slotpushButton()));
}
Widget::~Widget()
{
    
    
    delete ui;
}

/**
 * @brief 显示位置
 */
void Widget::displayPos()
{
    
    
    double lon = ui->lineEdit_lon->text().toDouble();
    double lat = ui->lineEdit_lat->text().toDouble();
    MAP_X_Y t_MAP_X_Y = AxesConvert(lon,lat);//经纬度转换为像素坐标

    m_pPainter->drawImage(0,0,QImage("./images/worldMap.jpg"));

    for(int i=t_MAP_X_Y.x;i<t_MAP_X_Y.x+5;i++)
        for(int j=t_MAP_X_Y.y;j<t_MAP_X_Y.y+5;j++)
        {
    
    
            m_pImage->setPixel(i,j,qRgb(255,0,0));//按像素点修改图片颜色,图片中显示为红色方块
        }
    ui->label->setPixmap(QPixmap::fromImage(*m_pImage));
}

/**
 * @brief 经纬度转换为像素坐标
 * @param lon 经度
 * @param lat 维度
 * @return 像素坐标
 */
MAP_X_Y Widget::AxesConvert(double lon, double lat)
{
    
    
    const double pixel_Width = 1024;//截取地图像素宽度
    const double pixel_Height = 1024;//截取地图像素高度
    const double PI = 3.1415926;
    const double MaxLon = 180;//截取地图的最大经度
    const double MaxLat = 85;//截取地图的最大维度
    int pixel_X;
    int pixel_Y;
    /**
     * @brief google地图中能够截取的最大经度是180度,最大维度是85度
     * 转换为平面坐标系后经度是均匀分布的,维度不是均匀分布
     *经过下面公式计算后,得到的“修正维度”是均匀的,传入MaxLat计算出来的值是修正维度的最大值
     */
    double reviseMaxLat = log(tan((90+MaxLat)*PI/360))/(PI/180);//修正后的最大维度

    lat = log(tan((90+lat)*PI/360))/(PI/180);//修正后的维度
    //平面坐标系可分为4个象限,坐标落在不同象限的计算方式不同
    if(lon>=0 && lat>=0)
    {
    
    
        pixel_X = (lon/MaxLon)*(pixel_Width/2)+pixel_Width/2;
        pixel_Y = (pixel_Height/2) - (lat/reviseMaxLat)*(pixel_Height/2);
    }
    else if(lon>=0 && lat<=0)
    {
    
    
        pixel_X = (lon/MaxLon)*(pixel_Width/2)+pixel_Width/2;
        pixel_Y = (pixel_Height/2) + (-lat/reviseMaxLat)*(pixel_Height/2);
    }
    else if(lon<=0 && lat >=0)
    {
    
    
        pixel_X = pixel_Width/2 - (-lon/MaxLon)*(pixel_Width/2);
        pixel_Y = (pixel_Height/2) - (lat/reviseMaxLat)*(pixel_Height/2);
    }
    else if(lon<=0 && lat<=0)
    {
    
    
        pixel_X = pixel_Width/2 - (-lon/MaxLon)*(pixel_Width/2);
        pixel_Y = (pixel_Height/2) + (-lat/reviseMaxLat)*(pixel_Height/2);
    }

    MAP_X_Y t_sMap;
    t_sMap.x = pixel_X;
    t_sMap.y = pixel_Y;
    return t_sMap;
}

void Widget::slotpushButton()
{
    
    
    displayPos();
}

Renderings showing the location of Beijing
Insert picture description here

Customized map: China surrounding

The following is an example of customizing a map around China, intercepting the longitude range from 60 degrees to 160 degrees, the latitude range from 0 degrees to 60 degrees, and the coordinate conversion function:

/**
 * @brief 经纬度转换为像素坐标
 * @param lon
 * @param lat
 * @return
 */
MAP_X_Y China_Map::AxesConvert_Custom(double lon, double lat)
{
    
    
    const double pixel_Width = 1143;//截取地图像素宽度
    const double pixel_Height = 859;//截取地图像素高度
    const double PI = 3.1415926;
    const double LeftLon = 60;//地图最左侧经度
    const double RightLon = 160;//地图最右侧经度
    const double TopLat = 60;//地图顶部维度
    const double BottomLat = 0;//地图底部维度
    int pixel_X;
    int pixel_Y;
    /**
     * @brief google地图中能够截取的最大经度是180度,最大维度是85度
     * 转换为平面坐标系后经度是均匀分布的,维度不是均匀分布
     *经过下面公式计算后,得到的“修正维度”是均匀的,传入MaxLat计算出来的值是修正维度的最大值
     */
    double reviseMaxLat = log(tan((90+(TopLat))*PI/360))/(PI/180);//修正后的最大维度

    lat = log(tan((90+lat)*PI/360))/(PI/180);//修正后的维度
    //截取的地图经度和维度都大于0,只集中在一个象限
    pixel_X = ((lon - LeftLon)/(RightLon - LeftLon))*pixel_Width;
    pixel_Y = pixel_Height - (lat - BottomLat)/(reviseMaxLat - BottomLat)*pixel_Height;

    MAP_X_Y t_sMap;
    t_sMap.x = pixel_X;
    t_sMap.y = pixel_Y;
    return t_sMap;
}

Renderings showing the location of Nanjing
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_40355471/article/details/107748833