QTは、経度と緯度の画像ピクセル座標への変換を実現します

QTは、経度と緯度の画像ピクセル座標への変換を実現します

ニーズの声明

最近、開発中にこの種の需要に遭遇しました。地球の経度と緯度を考慮して、静止画像マップ上で経度と緯度の位置をマークします。

需要分析

地球の緯度と経度は球面座標系です。画像は平面座標系であり、直接変換することはできません。GoogleMapsは、球面を平面に変換するときに「メルカトル投影法」を使用します(興味のある学生はBaidu)。座標系は依然として均一に分布していますが、寸法は均一に分布していません。平面座標系のピクセル座標を取得するには、特別な計算が必要です。

コード

世界地図の例

例として世界地図を取り上げます。最大の世界地図はGoogleマップにキャプチャされます:経度-180度から180度、緯度-85度から85度(メルカトル図法の後、地球の最大緯度は-90から90です。 90度は、無限大では平面を表現できない傾向があります)、アルゴリズムの中核は、不均一な次元を均一な表現に変換することです。
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();
}

北京の場所を示すレンダリング
ここに画像の説明を挿入

カスタマイズされた地図:中国周辺

以下は、中国周辺の地図をカスタマイズし、経度の範囲を60度から160度、緯度の範囲を0度から60度、および座標変換関数をインターセプトする例です。

/**
 * @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;
}

南京の場所を示すレンダリング
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_40355471/article/details/107748833