zoukankan      html  css  js  c++  java
  • 基于GDAL库海洋表温日平均计算工具设计与实现 C++版

    技术背景  

      在对物理海洋数据处理过程中,表层温度是众多要素中的一种,本文书要是针对海洋表温数据批量日平均处理的一个工具设计。首先要在对当前的SST数据文件作一下简要的说明,SST全称为sea surfer Temperature,文件后缀为.nc,文件里面主要有两个数据集(datasets),第一个数据集全球的海洋表温的温度数据,其中标记值为-999(float数据类型),第二个数据集为遗失数据补充说明,具体大家可以参考附件链接中的文本文件,表温数据集主要分为8个时间节点,每个时间节点是一层,共有八层,每一层的范围是全球范围,空间分辨率为0.25度,为了方便利用surfer软件打开,并进行进一步制图。需要进行日平均计算。

    计算原理

      首先将相应海峡范围的数据在读取的时候8个波段直接读上来,然后再将同一个栅格点上的8个波段的观测值进行相加,取平均后重新赋给当前栅格点;由于观测因素,部分栅格点或波段出现标记值,即数据缺失,所以在进行均值计算之前要进行数据的插值,本工具插值是采用反距离定权插值的方法,具体请参考GDAL库相关插值函数的使用方法。平均值计算出来以后,然后进行数据整理,数据整理主要是根据起始坐标、分辨率、栅格的宽度和高度,计算出每一个栅格点的坐标值,然后匹配上对应的表温数值,整合成三维点数据,打印出来。数据打印出来为txt数据。

      该工具可批量计算同一个文件下的所有文件下的所有SST数据(*.nc文件),生成相应的日平均数据。但是该程序对文件名具有限制性,格式必须为官方网站上下载的文件名称(例如:SEAFLUX-OSB-CDR_V02R00_SST_D20060101_C20160824.nc),这个可以根据源码进行修改。

    开发环境

      本工具采用GDAL库及其扩展库netCDF,开发平台为QT 5.11.2(MSVC 2017),开发语言为C++

    源码解析

      工具主要分为两个部分,即界面和核心功能,二者各占一个线程,通过信号和槽函数进行通信,界面代码如下:

    h文件

      1 #ifndef MAINWINDOWS_H
      2 #define MAINWINDOWS_H
      3 
      4 #include <QWidget>
      5 #include <QObject>
      6 #include <QString>
      7 #include <QDebug>
      8 #include <QDir>
      9 #include <QFileDialog>
     10 #include <QThread>
     11 #include <QIcon>
     12 
     13 #include "mdsst.h"
     14 
     15 namespace Ui {
     16 class MainWindows;
     17 }
     18 
     19 class MainWindows : public QWidget
     20 {
     21     Q_OBJECT
     22 
     23 public:
     24     explicit MainWindows(QWidget *parent = nullptr);
     25     ~MainWindows();
     26 
     27 private slots:
     28     void on_startBtn_clicked();
     29 
     30     void on_aboutBtn_clicked();
     31 
     32     void on_closeBtn_clicked();
     33 
     34     void on_inchooseBtn_clicked();
     35 
     36     void on_outchooseBtn_clicked();
     37 
     38     void infoshow(QString tempInfo);
     39 
     40     void completedInfoShow(QString info);
     41 
     42     void fileNumInfoShow(QString info);
     43 
     44     void compedFileNumshow(QString info);
     45 
     46 signals:
     47     void start(QString inputFilePath,QString outputFilePath);
     48 
     49 private:
     50     Ui::MainWindows *ui;
     51 
     52     MDSST *mdsst;
     53 
     54     QSharedPointer <QThread> mdsst_thd;
     55 
     56 };
     57 
     58 #endif // MAINWINDOWS_H

    cpp文件

      1 #include "mainwindows.h"
      2 #include "ui_mainwindows.h"
      3 
      4 MainWindows::MainWindows(QWidget *parent) :
      5     QWidget(parent),
      6     ui(new Ui::MainWindows)
      7 {
      8     ui->setupUi(this);
      9     infoshow("使用前请了解相关使用方法.");
     10 
     11     mdsst = new MDSST();
     12     connect(this, SIGNAL(start(QString,QString)), mdsst, SLOT(startprocess(QString,QString)));
     13     connect(mdsst, SIGNAL(showInfo(QString)), this, SLOT(infoshow(QString)));
     14     connect(mdsst, SIGNAL(showCompedInfo(QString)), this, SLOT(completedInfoShow(QString)));
     15     connect(mdsst, SIGNAL(showFileNumInfo(QString)), this, SLOT(fileNumInfoShow(QString)));
     16     connect(mdsst, SIGNAL(showCompedFileNum(QString)), this, SLOT(compedFileNumshow(QString)));
     17 
     18     mdsst_thd.reset(new QThread);
     19     mdsst->moveToThread(mdsst_thd.data());
     20     mdsst_thd->start();
     21 
     22     this->setFixedSize(this->size());
     23     //setWindowIcon(QIcon(":/logo.png"));
     24 }
     25 
     26 MainWindows::~MainWindows()
     27 {
     28     if(mdsst_thd->isRunning())
     29     {
     30         mdsst_thd->terminate();
     31         mdsst_thd->wait();
     32         mdsst_thd->quit();
     33     }
     34     delete ui;
     35 }
     36 
     37 void MainWindows::infoshow(QString tempInfo)
     38 {
     39     if(tempInfo == "所有文件已处理完毕!"){
     40         ui->startBtn->setEnabled(true);
     41     }
     42     ui->Infoshowtedt->append(tempInfo);
     43 }
     44 
     45 void MainWindows::on_startBtn_clicked()
     46 {
     47     ui->startBtn->setEnabled(false);
     48     QString inputFilePath = ui->inputledt->text();
     49     QString outputFilePath = ui->outputledt->text();
     50     if(inputFilePath == "" && outputFilePath == "")
     51     {
     52         infoshow("文件路径或保存路径有误!");
     53         ui->startBtn->setEnabled(true);
     54     }else{
     55         emit start(inputFilePath,outputFilePath);
     56     }
     57 }
     58 
     59 void MainWindows::on_aboutBtn_clicked()
     60 {
     61     QString info = "本工具只针对于海洋表温数据进行天平均处理,对于缺失数据已经进行了插值处理.";
     62     infoshow(info);
     63     info = "如有问题讨论或反馈,请联系制作人";
     64     infoshow(info);
     65     info = "制作:thyou,邮箱:thyou@vip.qq.com,时间:2018年12月22日";
     66     infoshow(info);
     67 }
     68 
     69 void MainWindows::on_closeBtn_clicked()
     70 {
     71     if(mdsst_thd->isRunning())
     72     {
     73         mdsst_thd->terminate();
     74         mdsst_thd->wait();
     75         mdsst_thd->quit();
     76     }
     77     close();
     78 }
     79 
     80 void MainWindows::on_inchooseBtn_clicked()
     81 {
     82     QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this,tr("选择"),QDir::currentPath()));
     83     if(directory != "")
     84     {
     85         ui->inputledt->setText(directory);
     86     }else
     87     {
     88         ui->Infoshowtedt->append("路径选择失败!");
     89     }
     90 }
     91 
     92 void MainWindows::on_outchooseBtn_clicked()
     93 {
     94     QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this,tr("选择"),QDir::currentPath()));
     95     if(directory != "")
     96     {
     97         ui->outputledt->setText(directory);
     98     }else
     99     {
    100         ui->Infoshowtedt->append("路径选择失败!");
    101     }
    102 }
    103 
    104 void MainWindows::completedInfoShow(QString info)
    105 {
    106     ui->completedledt->setText(info);
    107 }
    108 
    109 void MainWindows::fileNumInfoShow(QString info)
    110 {
    111     ui->fileNumledt->setText(info);
    112 }
    113 
    114 void MainWindows::compedFileNumshow(QString info)
    115 {
    116     ui->compedFileNumledt->setText(info);
    117 }
    118 

      工具界面布局如下:

    image

      核心功能实现步骤:获取输入路径下的所有nc文件,形成文件列表,根据列表的size进行循环,循环内部对单个文件执行单个文件的操作,该操作包括逐层插值函数、平均值计算、数据整理成三维点Point3D数据、写入文本等内容,循环结束,则处理完毕;为了方便用户使用,辅助添加了实时处理信息显示,批量文件处理进度等功能。具体源代码如下:

    h文件

      1 #ifndef MDSST_H
      2 #define MDSST_H
      3 
      4 #include <QObject>
      5 #include <vector>
      6 #include <gdal_priv.h>
      7 #include <QVector>
      8 #include <string>
      9 #include <QString>
     10 #include <QStringList>
     11 #include <QDebug>
     12 #include <odplib_extd.h>
     13 #include <QDir>
     14 #include <QFileDialog>
     15 #include <QDateTime>
     16 #include <gdalgrid.h>
     17 
     18 #pragma execution_character_set("utf-8")
     19 
     20 class MDSST : public QObject
     21 {
     22     Q_OBJECT
     23 public:
     24     explicit MDSST(QObject *parent = nullptr);
     25 
     26     void getNcFileNamesList(const QString &filePath, QStringList &tempFileList);
     27 
     28     void fileRead(QString filePath,NC_OBJ &temp_Obj,QString tempMark);
     29 
     30     //反距离权重插值函数
     31     void inverDistToPowerItpl(GRD_OBJ itplGRDOBJ , GRD_OBJ &itpledGRDOBJ , double pixResoultion);
     32 
     33     void inverDistToPowerItplProcess(NC_OBJ  &temp_Obj);
     34 
     35     void dataArrangement(GRD_OBJ temp_obj, QVector<QVector<float>> tempAT, QList<Point3D> &tempPL);
     36 
     37     void crateTxtFile(QString fileSavePath, QList<Point3D> tempPointList);
     38 
     39     void avageOfDailySST(NC_OBJ  temp_Obj, GRD_OBJ &temp_ATInfo, QVector<QVector<float>> &tempAvageTemper);
     40 
     41     void createFilePath(QString savePath, QString fileNam, QString &filePath);
     42 signals:
     43     void showInfo(QString tempInfo);
     44 
     45     void showCompedInfo(QString info);
     46 
     47     void showFileNumInfo(QString info);
     48 
     49     void showCompedFileNum(QString info);
     50 
     51 public slots:
     52     void startprocess(QString inputFilePath,QString outputFilePath);
     53 };
     54 
     55 #endif // MDSST_H

    cpp文件

      1 #include "mdsst.h"
      2 
      3 MDSST::MDSST(QObject *parent) : QObject(parent){}
      4 
      5 void MDSST::getNcFileNamesList(const QString &filePath, QStringList &tempFileList)
      6 {
      7     // 文件路径信息是否为空判断
      8     if(filePath == NULL){
      9         QString info = "输入路径有误!";
     10         emit showInfo(info);
     11         return;
     12     } else{
     13         QString info = "检索当前路径下的文件...";
     14         emit showInfo(info);
     15     }
     16 
     17     QDir dir(filePath);
     18     QStringList nameFilters;
     19     nameFilters << "*.nc" ;
     20     tempFileList = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name);
     21 
     22     QString info = "文件检索已完成,文件数量:";
     23     info += tempFileList.size();
     24     emit showInfo(info);
     25 }
     26 
     27 void MDSST::fileRead(QString filePath,NC_OBJ &temp_Obj,QString tempMark)
     28 {
     29     QByteArray  fpArr       = filePath.toLocal8Bit();
     30     const char* ncFilePath  = fpArr.data();
     31 
     32     GDALAllRegister();
     33     // 设置支持中文路径
     34     CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
     35     // 以只读方式打开数据集
     36     GDALDataset* fileDataset = (GDALDataset*) GDALOpen(ncFilePath,GA_ReadOnly);
     37     if (fileDataset == NULL)
     38     {
     39         QString info = "文件路径有误!";
     40         emit showInfo(info);
     41         return;
     42     }else{
     43         QString info = "读取文件...";
     44         emit showInfo(info);
     45     }
     46 
     47     // 获得数据的字符串,可以打印出来看看自己需要的数据在那
     48     char** sublist = GDALGetMetadata((GDALDatasetH) fileDataset,"SUBDATASETS");
     49 
     50     int iCount = CSLCount(sublist);
     51     if(iCount <= 0){
     52         QString info = filePath + "数据为空!";
     53         emit showInfo(info);
     54         GDALClose((GDALDriverH)fileDataset);
     55         return;
     56     }
     57 
     58     // 存储数据集信息
     59     for(int i = 0; sublist[i] != NULL;i++){
     60 
     61         // 打印数据集表述信息
     62         // qDebug() << sublist[i] << endl;
     63 
     64         if(i%2 != 0){
     65             continue;
     66         }
     67 
     68         QString tmpstr = sublist[i];
     69         tmpstr = tmpstr.mid(tmpstr.indexOf("=")+1);
     70         QByteArray  tmpstrArr = tmpstr.toLocal8Bit();
     71         const char* tmpc_str  = tmpstrArr.data();
     72 
     73         QString tmpdsc = sublist[i+1];
     74         tmpdsc = tmpdsc.mid(tmpdsc.indexOf("=")+1);
     75 
     76         GDALDataset* hTmpDt = (GDALDataset*)GDALOpen(tmpc_str,GA_ReadOnly);//打开该数据
     77 
     78         if (hTmpDt != NULL)
     79         {
     80             temp_Obj.dataSet.push_back(tmpc_str);
     81         }
     82         if(&temp_Obj.dSDesc != NULL){
     83             temp_Obj.dSDesc.push_back(tmpdsc);
     84         }
     85         GDALClose(hTmpDt);
     86     }
     87 
     88     temp_Obj.dSAttrInfo.resize(temp_Obj.dataSet.size());
     89     temp_Obj.dSValue.resize(temp_Obj.dataSet.size());
     90 
     91     QString qtmpdsc = temp_Obj.dSDesc[0];
     92     QStringList qtmpdsclist = qtmpdsc.split("");
     93     QString dataset_name = qtmpdsclist[1];
     94 
     95 
     96     for(int dsIdx = 0; dsIdx < temp_Obj.dataSet.size(); dsIdx++){
     97         string tempInfo = temp_Obj.dataSet[dsIdx].toStdString();
     98         GDALDataset* tempDt   = (GDALDataset*)GDALOpen(tempInfo.data(), GA_ReadOnly);
     99 
    100         double adfGeoTransform[6];
    101         if( tempDt->GetGeoTransform(adfGeoTransform) != CE_None ){
    102             QString info = filePath + "投影信息不存在!";
    103             emit showInfo(info);
    104             return;
    105         }
    106         temp_Obj.dSAttrInfo[dsIdx].bCount = tempDt->GetRasterCount();
    107         temp_Obj.dSValue[dsIdx].resize(tempDt->GetRasterCount());
    108 
    109         /***************************************************************
    110          *          大隅-吐噶啦海峡
    111          *          范围:
    112          *              126 E ~ 135E
    113          *              26  N ~ 34 N
    114          * *************************************************************/
    115 
    116         int  iStartX = floor((126 - adfGeoTransform[0]) / adfGeoTransform[1]);
    117         int  iStartY = floor((34  - adfGeoTransform[3]) / adfGeoTransform[5]);
    118         int  iSizeX  = floor((135 - 126) / adfGeoTransform[1]);
    119         int  iSizeY  = floor((26  - 34 ) / adfGeoTransform[5]);
    120 
    121         temp_Obj.dSAttrInfo[dsIdx].orgLocat.x   = adfGeoTransform[0] + iStartX*adfGeoTransform[1] + iStartY*adfGeoTransform[2];
    122         temp_Obj.dSAttrInfo[dsIdx].orgLocat.y   = adfGeoTransform[3] + iStartX*adfGeoTransform[4] + iStartY*adfGeoTransform[5];
    123         temp_Obj.dSAttrInfo[dsIdx].pixelSize.x  = adfGeoTransform[1];
    124         temp_Obj.dSAttrInfo[dsIdx].pixelSize.y  = adfGeoTransform[5];
    125         temp_Obj.dSAttrInfo[dsIdx].rXSize       = iSizeX;
    126         temp_Obj.dSAttrInfo[dsIdx].rYSize       = iSizeY;
    127 
    128         QString dataSetNam = temp_Obj.dataSet[dsIdx];
    129         QString info = "正在解析" + dataSetNam + "...";
    130         emit showInfo(info);
    131 
    132         int pbnMax = tempDt->GetRasterCount();
    133         int *pBandMap = new int[pbnMax];
    134         for(int pbn = 0; pbn<pbnMax;pbn++){
    135             pBandMap[pbn] = pbn + 1;
    136         }
    137         /**********获取数据类型,定义缓存空间大小*******************
    138 
    139         GDALRasterBand* pBand = tempDt->GetRasterBand(1);
    140         GDALDataType dataType = pBand->GetRasterDataType();
    141 
    142         ********************************************************/
    143 
    144         float* lineData = new float[pbnMax*iSizeX*iSizeY];
    145         tempDt->RasterIO(GF_Read, iStartX, iStartY, iSizeX, iSizeY,lineData,iSizeX, iSizeY, GDT_Float32, pbnMax, pBandMap, 0, 0, 0);
    146 
    147         int BandNumMax  = pbnMax;
    148         int iLineMax    = iSizeY;
    149         int iPixelMax   = iSizeX;
    150 
    151         for(int BandNum = 0;BandNum<BandNumMax;BandNum++){
    152             int tempBN = BandNum + 1;
    153 
    154             temp_Obj.dSValue[dsIdx][BandNum].resize(iLineMax);
    155             for (int iLine = 0; iLine < iLineMax; iLine++)
    156             {
    157                 temp_Obj.dSValue[dsIdx][BandNum][iLine].resize(iPixelMax);
    158                 for (int iPixel = 0; iPixel < iPixelMax; iPixel++)
    159                 {
    160                     int index = BandNum * iLineMax * iPixelMax + iLine * iPixelMax + iPixel;
    161                     temp_Obj.dSValue[dsIdx][BandNum][iLine][iPixel] = lineData[index];
    162                 }
    163             }
    164 
    165             info = "波段" + QString::number(tempBN) + "已完成.";
    166             emit showInfo(info);
    167         }
    168 
    169         delete [] lineData;
    170         lineData = NULL;
    171         GDALClose((GDALDatasetH)tempDt);
    172 
    173         info = dataSetNam + "解析已完成.";
    174         emit showInfo(info);
    175     }
    176 
    177     QString info = filePath + "读取已完成.";
    178     emit showInfo(info);
    179     GDALClose(fileDataset);
    180 }
    181 
    182 void MDSST::inverDistToPowerItpl(GRD_OBJ itplGRDOBJ,GRD_OBJ &itpledGRDOBJ,double pixResoultion)
    183 {
    184     // 相关参数信息是否为空判断
    185     if(pixResoultion == NULL){
    186         qDebug() << __FUNCTION__
    187                  << "tempPoint3d: data is empty!"
    188                  << __LINE__
    189                  << endl;
    190         return;
    191     }else if(itplGRDOBJ.dSAttrInfo.rXSize == NULL){
    192         qDebug() << __FUNCTION__
    193                  << "tempGRDOBJ: data is empty!"
    194                  << __LINE__
    195                  << endl;
    196         return;
    197     }else{
    198         QString info = "对当前文件进行插值处理...";
    199         emit showInfo(info);
    200         qDebug() << "start inverDistToPowerItpl ..." << endl;
    201     }
    202 
    203     // 有效数据筛选,剔除标记值
    204     QList<Point3D> filterPoint3d;
    205     for(int i = 0;i<itplGRDOBJ.dSValue.size();i++){
    206         for(int j = 0;j<itplGRDOBJ.dSValue[i].size();j++){
    207 
    208             double tempValue = itplGRDOBJ.dSValue[i][j];
    209             if(tempValue == -999){
    210                 continue;
    211             }
    212             Point3D tempP3d;
    213             tempP3d.y = i + 1;
    214             tempP3d.x = j + 1;
    215             tempP3d.z = tempValue;
    216             filterPoint3d.append(tempP3d);
    217         }
    218     }
    219 
    220     // 定义散点总数
    221     int nPoints = filterPoint3d.size();
    222 
    223     // 定义插值空间范围
    224     double dfXMin = 0;
    225     double dfXMax = itplGRDOBJ.dSAttrInfo.rXSize;
    226     double dfYMin = 0;
    227     double dfYMax = itplGRDOBJ.dSAttrInfo.rYSize;
    228 
    229     // 定义散点坐标信息
    230     double* padfX = new double[nPoints];
    231     double* padfY = new double[nPoints];
    232     double* padfZ = new double[nPoints];
    233 
    234     for(int i = 0;i<nPoints;i++){
    235         padfX[i] = filterPoint3d[i].x;
    236         padfY[i] = filterPoint3d[i].y;
    237         padfZ[i] = filterPoint3d[i].z;
    238     }
    239 
    240     int nXSize = (dfXMax-dfXMin)*abs(itplGRDOBJ.dSAttrInfo.pixelSize.x)/pixResoultion;
    241     int nYSize = (dfYMax-dfYMin)*abs(itplGRDOBJ.dSAttrInfo.pixelSize.y)/pixResoultion;
    242 
    243     // 构造插值算法参数并设置差值参数值
    244     GDALGridInverseDistanceToAPowerOptions* poOptions = new GDALGridInverseDistanceToAPowerOptions();
    245     // 权重指数
    246     poOptions->dfPower   = 2;
    247     // 搜索椭圆第一半径
    248     poOptions->dfRadius1 = 20;
    249     // 搜索椭圆第二半径
    250     poOptions->dfRadius2 = 15;
    251 
    252     //定义插值后输出数据组
    253     float* lineData = new float[nXSize*nYSize];
    254 
    255     //反距离权重插值(IDW)
    256     GDALGridCreate(GGA_InverseDistanceToAPower,poOptions,nPoints,padfX,padfY,padfZ,dfXMin,dfXMax,dfYMin,dfYMax,nXSize,nYSize,GDT_Float32,lineData,NULL,NULL);
    257 
    258     //数据信息整理
    259     itpledGRDOBJ.dataSet = itplGRDOBJ.dataSet;
    260     itpledGRDOBJ.dSDesc  = itplGRDOBJ.dSDesc;
    261 
    262     itpledGRDOBJ.dSAttrInfo.bCount = itplGRDOBJ.dSAttrInfo.bCount;
    263     itpledGRDOBJ.dSAttrInfo.orgLocat = itplGRDOBJ.dSAttrInfo.orgLocat;
    264 
    265     if(itplGRDOBJ.dSAttrInfo.pixelSize.x == abs(itplGRDOBJ.dSAttrInfo.pixelSize.x)){
    266         itpledGRDOBJ.dSAttrInfo.pixelSize.x = pixResoultion;
    267     }else{
    268         itpledGRDOBJ.dSAttrInfo.pixelSize.x = -1 * pixResoultion;
    269     }
    270     if(itplGRDOBJ.dSAttrInfo.pixelSize.x == abs(itplGRDOBJ.dSAttrInfo.pixelSize.x)){
    271         itpledGRDOBJ.dSAttrInfo.pixelSize.y = pixResoultion;
    272     }else{
    273         itpledGRDOBJ.dSAttrInfo.pixelSize.y = -1 * pixResoultion;
    274     }
    275 
    276     itpledGRDOBJ.dSAttrInfo.rXSize = nXSize;
    277     itpledGRDOBJ.dSAttrInfo.rYSize = nYSize;
    278 
    279     // 插值数据存储
    280     QVector<QVector<float>> tempValue;
    281     tempValue.resize(nYSize);
    282     for(int lineNum = 0;lineNum<nYSize;lineNum++){
    283         tempValue[lineNum].resize(nXSize);
    284         for(int pixalNum = 0;pixalNum<nXSize;pixalNum++){
    285             tempValue[lineNum][pixalNum] = lineData[lineNum*nXSize+pixalNum];
    286         }
    287     }
    288 
    289     itpledGRDOBJ.dSValue.append(tempValue);
    290 
    291     delete poOptions;
    292     delete [] lineData;
    293 
    294     QString info = "插值处理完成.";
    295     emit showInfo(info);
    296 }
    297 
    298 void MDSST::avageOfDailySST(NC_OBJ  temp_Obj,GRD_OBJ &temp_ATInfo,QVector<QVector<float>> &tempAvageTemper)
    299 {
    300     // 数据存储信息是否为空判断
    301     if(temp_Obj.dSValue[0].size() == 0){
    302         return;
    303     }else if(temp_Obj.dSValue[0][0].size() == 0){
    304         return;
    305     }else if(temp_Obj.dSValue[0][0][0].size() == 0){
    306         return;
    307     }else{
    308         //数据值存在
    309         qDebug() << "check data info completed,no error." << endl;
    310         QString info = "对插值后的数据进行检查...";
    311         emit showInfo(info);
    312     }
    313 
    314     //存储当前的数据信息
    315     if(temp_ATInfo.dataSet.isEmpty()){
    316         temp_ATInfo.dataSet = temp_Obj.dataSet[0];
    317         temp_ATInfo.dSDesc  = temp_Obj.dSDesc[0];
    318 
    319         temp_ATInfo.dSAttrInfo = temp_Obj.dSAttrInfo[0];
    320         temp_ATInfo.dSAttrInfo.bCount = 1;
    321     }
    322 
    323     // 插值处理--反距离定权插值
    324     inverDistToPowerItplProcess(temp_Obj);
    325 
    326     // 日均值计算 处理对象为SST表温数据
    327     qDebug() << "start calc average temperature of sea..." << endl;
    328     QString info = "对当前数据进行日平均计算...";
    329     emit showInfo(info);
    330     tempAvageTemper.resize(temp_Obj.dSValue[0][0].size());
    331     for(int i = 0;i < temp_Obj.dSValue[0][0].size();i++){
    332 
    333         tempAvageTemper[i].resize(temp_Obj.dSValue[0][0][i].size());
    334         for(int j = 0;j < temp_Obj.dSValue[0][0][i].size();j++){
    335 
    336             float   tempNum     = 0;
    337             int     avgNum      = 0;
    338             float   tempMark    = 0;
    339 
    340             for(int k = 0;k < temp_Obj.dSValue[0].size();k++){
    341                 float tempValue = temp_Obj.dSValue[0][k][i][j];
    342                 if(tempValue == -999){
    343                     tempMark = temp_Obj.dSValue[0][k][i][j];
    344                     continue;
    345                 }
    346                 avgNum  += 1;
    347                 tempNum += temp_Obj.dSValue[0][k][i][j];
    348             }
    349 
    350             if(avgNum == 0){
    351                 tempAvageTemper[i][j] = tempMark;
    352             }else{
    353                 tempNum = tempNum/avgNum;
    354                 tempAvageTemper[i][j] = tempNum;
    355             }
    356 
    357         }
    358     }
    359     qDebug() << "Daily mean temperature of sea_surface is received." << endl;
    360     info = "计算完成.";
    361     emit showInfo(info);
    362 }
    363 
    364 void MDSST::inverDistToPowerItplProcess(NC_OBJ  &temp_Obj)
    365 {
    366     // 数据存储信息是否为空判断
    367     if(temp_Obj.dSValue[0].size() == 0){
    368         qDebug() << __FUNCTION__
    369                  << "temp_Obj: data is empty!"
    370                  << __LINE__
    371                  << endl;
    372         return;
    373     }else if(temp_Obj.dSValue[0][0].size() == 0){
    374         qDebug() << __FUNCTION__
    375                  << "temp_Obj: data is empty!"
    376                  << __LINE__
    377                  << endl;
    378         return;
    379     }else if(temp_Obj.dSValue[0][0][0].size() == 0){
    380         qDebug() << __FUNCTION__
    381                  << "temp_Obj: data is empty!"
    382                  << __LINE__
    383                  << endl;
    384         return;
    385     }else{
    386         //数据值存在
    387         qDebug() << "check data info completed,ItplProcess start ..." << endl;
    388     }
    389 
    390     GRD_OBJ   itplGRDOBJ;
    391 
    392     for(int dsIdx = 0; dsIdx < temp_Obj.dataSet.size(); dsIdx++){
    393 
    394         itplGRDOBJ.dataSet = temp_Obj.dataSet[dsIdx];
    395         itplGRDOBJ.dSDesc  = temp_Obj.dSDesc[dsIdx];
    396 
    397         itplGRDOBJ.dSAttrInfo = temp_Obj.dSAttrInfo[dsIdx];
    398         itplGRDOBJ.dSAttrInfo.bCount = 1;
    399 
    400         for(int BandNum = 0;BandNum<temp_Obj.dSAttrInfo[dsIdx].bCount;BandNum++){
    401 
    402             itplGRDOBJ.dSValue.append(temp_Obj.dSValue[dsIdx][BandNum]);
    403             GRD_OBJ itpledGRDOBJ;
    404             inverDistToPowerItpl(itplGRDOBJ,itpledGRDOBJ,0.25);
    405             temp_Obj.dSValue[dsIdx][BandNum].clear();
    406             temp_Obj.dSValue[dsIdx][BandNum].append(itpledGRDOBJ.dSValue);
    407         }
    408     }
    409 
    410     qDebug() << "ItplProcess completed." << endl;
    411 }
    412 
    413 void MDSST::dataArrangement(GRD_OBJ temp_obj, QVector<QVector<float>> tempAT, QList<Point3D> &tempPL)
    414 {
    415     // 路径信息是否为空判断
    416     if(temp_obj.dSAttrInfo.rXSize == NULL){
    417         qDebug() << __FUNCTION__
    418                  << "temp_obj:data is empty!"
    419                  << __LINE__
    420                  << endl;
    421         return;
    422     }else if(tempAT.size() == 0){
    423         qDebug() << __FUNCTION__
    424                  << "tempAT:data is empty!"
    425                  << __LINE__
    426                  << endl;
    427         return;
    428     }else{
    429         qDebug() << "start dataArrangement ...." << endl;
    430         QString info = "整理当前成果数据...";
    431         emit showInfo(info);
    432     }
    433 
    434     double iXStart = temp_obj.dSAttrInfo.orgLocat.x;
    435     double iYStart = temp_obj.dSAttrInfo.orgLocat.y;
    436     double iXPixel = temp_obj.dSAttrInfo.pixelSize.x;
    437     double iYPixel = temp_obj.dSAttrInfo.pixelSize.y;
    438 
    439     double iXSize  = temp_obj.dSAttrInfo.rXSize;
    440     double iYSize  = temp_obj.dSAttrInfo.rYSize;
    441 
    442     for(int i = 0;i<iYSize;i++){
    443         double B = iYStart + i * iYPixel;
    444         for(int j = 0;j<iXSize;j++){
    445             double L = iXStart + j * iXPixel;
    446 
    447             Point3D tempP;
    448             tempP.x = B;
    449             tempP.y = L;
    450             tempP.z = tempAT[i][j];
    451 
    452             tempPL.append(tempP);
    453         }
    454     }
    455 
    456     QString info = "整理完毕.";
    457     emit showInfo(info);
    458     qDebug() << "Point infomation arrange completed!" << endl;
    459 }
    460 
    461 void MDSST::createFilePath(QString savePath, QString fileNam, QString &filePath)
    462 {
    463     QDateTime local(QDateTime::currentDateTime());
    464     QString localTime = local.toString("yyyyMMdd");
    465     //文件名称格式为SEAFLUX-OSB-CDR_V02R00_SST_D20060101_C20160824.nc
    466     QString tempStr = fileNam.split("_")[3];
    467     filePath = savePath + "/SEAFLUX-OSB-CDR_V02R00_SST_" + tempStr+ "_C" + localTime + ".txt";
    468 }
    469 
    470 void MDSST::crateTxtFile(QString fileSavePath, QList<Point3D> tempPointList)
    471 {
    472     QFile file(fileSavePath);
    473     /******************************************************************
    474     if(!file.open(QIODevice::WriteOnly))
    475     {
    476         qDebug() << "Open failed, please check the file path!" << endl;
    477         return;
    478     }
    479     ******************************************************************/
    480 
    481     QString info = "写入文件" + fileSavePath;
    482     emit showInfo(info);
    483     if(file.open(QFile::ReadWrite)){
    484         for(int i = 0; i<tempPointList.size();i++){
    485 
    486             /******************************************************************
    487             QString tempPointInfo = QString::number(tempPointList[i].x) + "," +
    488                                     QString::number(tempPointList[i].y) + "," +
    489                                     QString::number(tempPointList[i].z) + "
    ";
    490             file.write(tempPointInfo.toUtf8());
    491             ******************************************************************/
    492             QTextStream outPut(&file);
    493             outPut << tempPointList[i].x
    494                    <<","
    495                    << tempPointList[i].y
    496                    <<","
    497                    << tempPointList[i].z
    498                    <<endl;
    499         }
    500     }else{
    501         qDebug() << "Open failed, please check the file path!" << endl;
    502         return;
    503     }
    504 
    505     file.close();
    506 
    507     QString fileName = fileSavePath.split("/")[fileSavePath.split("/").size()-1];
    508     qDebug() << "File "
    509              << fileName
    510              << "write completed!"
    511              << endl;
    512 
    513     info = fileName + "写入完成.";
    514     emit showInfo(info);
    515 }
    516 
    517 void MDSST::startprocess(QString inputFilePath,QString outputFilePath)
    518 {
    519 
    520     inputFilePath  = inputFilePath.replace(QString("\"),QString("/"));
    521     outputFilePath = outputFilePath.replace(QString("\"),QString("/"));
    522 
    523     QStringList fileList;
    524     getNcFileNamesList(inputFilePath,fileList);
    525 
    526     emit showFileNumInfo(QString::number(fileList.size()));
    527     for(int i = 0;i<fileList.size();i++){
    528         QString filePath = inputFilePath + "/" + fileList[i];
    529 
    530         NC_OBJ     Obj;
    531         GRD_OBJ aTInfo;
    532         QList<Point3D> pList;
    533         QVector<QVector<float>> avageTemper;
    534 
    535         QString tempinfo = QString::number((i+0.3)*100/fileList.size()) + "%";
    536         emit showCompedInfo(tempinfo);
    537         fileRead(filePath,Obj,"SST");
    538 
    539         tempinfo = QString::number((i+0.6)*100/fileList.size()) + "%";
    540         emit showCompedInfo(tempinfo);
    541         avageOfDailySST(Obj,aTInfo,avageTemper);
    542 
    543         tempinfo = QString::number((i+0.9)*100/fileList.size()) + "%";
    544         emit showCompedInfo(tempinfo);
    545         dataArrangement(aTInfo,avageTemper,pList);
    546 
    547         QString savePath = "";
    548         createFilePath(outputFilePath,fileList[i],savePath);
    549         crateTxtFile(savePath,pList);
    550         tempinfo = QString::number((i+1)*100/fileList.size()) + "%";
    551         emit showCompedInfo(tempinfo);
    552 
    553         tempinfo = QString::number(i + 1);
    554         emit showCompedFileNum(tempinfo);
    555     }
    556     emit showInfo("所有文件已处理完毕!");
    557 }

      文件输出以后,即可进行导入到Surfer软件中,进行进一步的编辑操作。

    运行结果

      原始数据截图

    image

      程序运行截图

    image

      成果数据截图

    image

      至此,小工具设计完成了!

      源码我已经上传至博客园了,下载地址:https://files.cnblogs.com/files/thyou/CT_MDSST.7z,希望能对处理SST数据这方面的同学有一丝帮助。

    致谢

      最后,感谢李民录老师前期对我在GDAL库方面的技术指导!

  • 相关阅读:
    理解java的三大特性之封装
    特征学习
    Java类编译、加载、和执行
    榜样
    组合学习模型
    python的re模块详解
    python的argpare和click模块详解
    vue的组件
    vue的表单输入绑定
    vue的事件处理梳理
  • 原文地址:https://www.cnblogs.com/thyou/p/10162489.html
Copyright © 2011-2022 走看看