Manual-Labeling-Tool/Manual-Labeling-Client/WindDataOperator/WindDataFileOperator.cpp

410 lines
14 KiB
C++

#include "WindDataFileOperator.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <filesystem>
/*
* 风场数据格式说明
* 'LAMPWINDDASASET', Height , Width , TIMENUM ,// : int64_t
* 'GEOTRANSFORMER',ESPGCODE,T1,T2,T3,T4,T5,T6
* "WINUV" , TIMELB, UArr[HxWxN],Varr[HxWxN] // double
*/
#define LAMP_WIND_SIGNAL_NUM 15
#define LAMP_WIND_GEOTRANSFORMER_NUM 14
#define LAMP_WIND_WINUV_NUM 6
LAMPWindDataDLL DataFileInfo getDataFileInfo(const char* filepath)
{
DataFileInfo info = { 0 };
info.Height=-1;
info.Width = -1;
info.Num = -1;
info.firstTimestamp = -1;
info.lastTimestamp = -1;
info.minLon=-1;
info.maxLon=-1;
info.minLat=-1;
info.maxLat=-1;
info.ESPGCODE = -1;
info.T11=-1;
info.T12=-1;
info.T13=-1;
info.T21=-1;
info.T22=-1;
info.T23=-1;
info.fileSize = -1;
std::ifstream file(filepath, std::ios::binary);
if (!file.is_open()) {
std::cerr << "无法打开文件: " << filepath << std::endl;
return info;
}
// 获取文件大小
file.seekg(0, std::ios::end);
info.fileSize = file.tellg();
file.seekg(0, std::ios::beg);
const char Fileheader[LAMP_WIND_SIGNAL_NUM]={ 0x4C, 0x41, 0x4D ,0x50, 0x57, 0x49, 0x4E, 0x44, 0x44 ,0x41, 0x53 ,0x41 ,0x53, 0x45 ,0x54 }; // LAMPWINDDASASET
const char GeoTransHeader[LAMP_WIND_GEOTRANSFORMER_NUM] = { 0x47 ,0x45 ,0x4F ,0x54 ,0x52 ,0x41 ,0x4E ,0x53 ,0x46 ,0x4F ,0x52 ,0x4D ,0x45 ,0x52 }; // GEOTRANSFORMER
const char WindUVHeader[LAMP_WIND_WINUV_NUM] = { 0x57 ,0x49 ,0x4E ,0x44 ,0x55 ,0x56 }; // WINDUV
char labelchar = '\0';
for (int64_t i = 0; i < LAMP_WIND_SIGNAL_NUM; i++) { // 处理头文件
file.read(reinterpret_cast<char*>(&labelchar), 1);
if (labelchar != Fileheader[i]) {
file.close();
return info;
}
}
// 读取基本维度信息
file.read(reinterpret_cast<char*>(&info.Height), sizeof(int64_t)); // H
file.read(reinterpret_cast<char*>(&info.Width), sizeof(int64_t)); // W
file.read(reinterpret_cast<char*>(&info.Num), sizeof(int64_t)); // N
if (info.Num == 0 || info.Height == 0 || info.Width == 0) {
file.close();
return info;
}
// 读取地理变换参数
for (int64_t i = 0; i < LAMP_WIND_GEOTRANSFORMER_NUM; i++) { // 读取标识
file.read(reinterpret_cast<char*>(&labelchar), 1);
if (labelchar != GeoTransHeader[i]) {
file.close();
return info;
}
}
// 读取数据
file.read(reinterpret_cast<char*>(&info.ESPGCODE), sizeof(int64_t));
file.read(reinterpret_cast<char*>(&info.T11), sizeof(double));
file.read(reinterpret_cast<char*>(&info.T12), sizeof(double));
file.read(reinterpret_cast<char*>(&info.T13), sizeof(double));
file.read(reinterpret_cast<char*>(&info.T21), sizeof(double));
file.read(reinterpret_cast<char*>(&info.T22), sizeof(double));
file.read(reinterpret_cast<char*>(&info.T23), sizeof(double));
// 计算经纬度范围(根据地理变换参数估算)
info.minLon = info.T11;
info.maxLon = info.T11 + info.Width * info.T12;
info.minLat = info.T21 + info.Height * info.T23;
info.maxLat = info.T21;
// 从数据中抽取
for (int64_t i = 0; i < LAMP_WIND_WINUV_NUM; i++) {
file.read(reinterpret_cast<char*>(&labelchar), 1);
if (labelchar != WindUVHeader[i]) {
file.close();
return info;
}
}
std::vector<int64_t> timeArr(info.Num);
for (int64_t t = 0; t < info.Num; t++) {
file.read(reinterpret_cast<char*>(&timeArr[t]), sizeof(int64_t));
int64_t datalen = int64_t(info.Height) * int64_t(info.Width) * 2 * sizeof(double);
file.seekg(datalen, std::ios::cur);
if (file.eof()) {
if (t == info.Num - 1) { // 所有的数据都被处理
break;
}
else {
file.close();
return info;
}
}
else {}
}
std::vector<int64_t>::iterator minIter = std::min_element(timeArr.begin(),timeArr.end());
std::vector<int64_t>::iterator maxIter = std::max_element(timeArr.begin(),timeArr.end());
info.firstTimestamp = *minIter;
info.lastTimestamp = *maxIter;
file.close();
return info;
}
LAMPWindDataDLL int32_t get_WindDataFileTimeArr(const char* filepath, DataFileInfo info, int64_t* outtimeArr)
{
if (info.Num <= 0 || outtimeArr == nullptr) {
return -1;
}
std::ifstream file(filepath, std::ios::binary);
if (!file.is_open()) {
return -2;
}
int64_t offset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET
+ 3 * sizeof(int64_t)
+ LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER
+ sizeof(int64_t)
+ sizeof(double) * 6
+ LAMP_WIND_WINUV_NUM; // WINUV
file.seekg(offset, std::ios::beg);
for (int64_t t = 0; t < info.Num; t++) {
file.read(reinterpret_cast<char*>(&outtimeArr[t]), sizeof(int64_t));
int64_t datalen = int64_t(info.Height) * int64_t(info.Width) * 2 * sizeof(double);
file.seekg(datalen, std::ios::cur);
if (file.eof()) {
if (t == info.Num - 1) { // 所有的数据都被处理
break;
}
else {
file.close();
return -1;
}
}
else {}
}
file.close();
return 0;
}
LAMPWindDataDLL int32_t Read_WindDataFile(const char* filepath, DataFileInfo info, int32_t timeID, double* UArr, double* VArr)
{
if (timeID < 0 || timeID >= info.Num || UArr == nullptr || VArr == nullptr) {
return -1;
}
std::ifstream file(filepath, std::ios::binary);
if (!file.is_open()) {
return -2;
}
// 判断信息
file.seekg(0, std::ios::end);
int64_t fileSize = file.tellg();
file.seekg(0, std::ios::beg);
if (fileSize != info.fileSize) {
file.close();
return -3;
}
int64_t Headeroffset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET
+ 3 * sizeof(int64_t)
+ LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER
+ sizeof(int64_t)
+ sizeof(double) * 6
+ LAMP_WIND_WINUV_NUM; // WINUV
int64_t U_block_len= int64_t(info.Height) * int64_t(info.Width)* sizeof(double);
int64_t V_block_len= int64_t(info.Height) * int64_t(info.Width)* sizeof(double);
int64_t datalen = sizeof(int64_t) // Time
+ U_block_len
+ V_block_len;
int64_t dataOffset = timeID * datalen;
int64_t sumOffset = Headeroffset + dataOffset;
if(sumOffset+datalen<=fileSize){}
else {
file.close();
return -4;
}
file.seekg(sumOffset, std::ios::beg);
int64_t timeInt = 0;
file.read(reinterpret_cast<char*>(&timeInt), sizeof(int64_t));
file.read(reinterpret_cast<char*>(UArr), U_block_len);
file.read(reinterpret_cast<char*>(VArr), V_block_len);
file.close();
return 0;
}
LAMPWindDataDLL int32_t Write_WindDataFile(const char* filepath, DataFileInfo info, int64_t timeInt,int32_t timeID, double* UArr, double* VArr)
{
const char Fileheader[LAMP_WIND_SIGNAL_NUM] = { 0x4C, 0x41, 0x4D ,0x50, 0x57, 0x49, 0x4E, 0x44, 0x44 ,0x41, 0x53 ,0x41 ,0x53, 0x45 ,0x54 }; // LAMPWINDDASASET
const char GeoTransHeader[LAMP_WIND_GEOTRANSFORMER_NUM] = { 0x47 ,0x45 ,0x4F ,0x54 ,0x52 ,0x41 ,0x4E ,0x53 ,0x46 ,0x4F ,0x52 ,0x4D ,0x45 ,0x52 }; // GEOTRANSFORMER
const char WindUVHeader[LAMP_WIND_WINUV_NUM] = { 0x57 ,0x49 ,0x4E ,0x44 ,0x55 ,0x56 }; // WINDUV
if (timeID < 0 || timeID >= info.Num || UArr == nullptr || VArr == nullptr) {
return -1;
}
// 判断文件是否存在
if (! std::filesystem::exists(filepath)) { // 文件不存在
std::fstream file(filepath, std::ios::binary | std::ios::in | std::ios::out);
if (!file.is_open()) { // 如果文件不存在,创建新文件并写入完整结构
file.open(filepath, std::ios::binary | std::ios::out);
if (!file.is_open()) {
return -2;
}
// 写入文件头
for (int64_t i = 0; i < LAMP_WIND_SIGNAL_NUM; i++) {
file.write(reinterpret_cast<const char*>(&Fileheader[i]), sizeof(char));
}
// 写入文件信息
file.write(reinterpret_cast<const char*>(&info.Height), sizeof(int64_t)); // H
file.write(reinterpret_cast<const char*>(&info.Width), sizeof(int64_t)); // W
file.write(reinterpret_cast<const char*>(&info.Num), sizeof(int64_t)); // N
// 写入地理变换参数
for (int64_t i = 0; i < LAMP_WIND_GEOTRANSFORMER_NUM; i++) {
file.write(reinterpret_cast<const char*>(&GeoTransHeader[i]), sizeof(char));
}
file.write(reinterpret_cast<const char*>(&info.ESPGCODE), sizeof(int64_t));
file.write(reinterpret_cast<const char*>(&info.T11), sizeof(double));
file.write(reinterpret_cast<const char*>(&info.T12), sizeof(double));
file.write(reinterpret_cast<const char*>(&info.T13), sizeof(double));
file.write(reinterpret_cast<const char*>(&info.T21), sizeof(double));
file.write(reinterpret_cast<const char*>(&info.T22), sizeof(double));
file.write(reinterpret_cast<const char*>(&info.T23), sizeof(double));
// 写入风场数据标签
for (int64_t i = 0; i < LAMP_WIND_WINUV_NUM; i++) {
file.write(reinterpret_cast<const char*>(&WindUVHeader[i]), sizeof(char));
}
// 写入风场块
std::vector<double> blockData(info.Width);
for (int64_t i = 0; i < info.Width; i++) {
blockData[i] = 0;
}
for (int64_t tid = 0; tid < info.Num; tid++) {
int64_t timeValue = 0;
if (tid == timeID) { //
timeValue = timeInt;
file.write(reinterpret_cast<const char*>(&timeValue), sizeof(int64_t));
file.write(reinterpret_cast<const char*>(UArr), info.Height*info.Width * sizeof(double));
file.write(reinterpret_cast<const char*>(VArr), info.Height*info.Width * sizeof(double));
timeValue = 0;
}
else {
file.write(reinterpret_cast<const char*>(&timeValue), sizeof(int64_t));
for (int64_t i = 0; i < info.Height; i++) { // U
file.write(reinterpret_cast<const char*>(blockData.data()), info.Width*sizeof(double));
}
for (int64_t i = 0; i < info.Height; i++) { // V
file.write(reinterpret_cast<const char*>(blockData.data()), info.Width*sizeof(double));
}
}
}
file.close();
}
}
else {
std::fstream file(filepath, std::ios::binary | std::ios::in | std::ios::out);
// 计算数据维度
int64_t Headeroffset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET
+ 3 * sizeof(int64_t)
+ LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER
+ sizeof(int64_t)
+ sizeof(double) * 6
+ LAMP_WIND_WINUV_NUM; // WINUV
file.seekp(LAMP_WIND_SIGNAL_NUM, std::ios::beg);
int64_t height = 0;
int64_t width = 0;
int64_t num = 0;
file.read(reinterpret_cast<char*>(&height), sizeof(int64_t));
file.read(reinterpret_cast<char*>(&width), sizeof(int64_t));
file.read(reinterpret_cast<char*>(&num), sizeof(int64_t));
if (info.Width != width || info.Height != height||info.Num<num) {
return -3;
}
if (info.Num > num) { // 修改长度
int64_t offset = LAMP_WIND_SIGNAL_NUM +2 * sizeof(int64_t);
file.seekg(offset, std::ios::beg);
file.write(reinterpret_cast<char*>(&info.Num), sizeof(int64_t)); // 修改长度
offset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET
+ 3 * sizeof(int64_t)
+ LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER
+ sizeof(int64_t)
+ sizeof(double) * 6
+ LAMP_WIND_WINUV_NUM
+ int64_t(sizeof(int64_t) + int64_t(info.Width) * int64_t(info.Height) * sizeof(double) * 2) * num;
file.seekg(offset, std::ios::beg);// 移动到 [n-1] >>|<<[n] 块
// 结果补零
std::vector<double> blockData(info.Width);
for (int64_t i = 0; i < info.Width; i++) {
blockData[i] = 0;
}
for (int64_t tid = num; tid < info.Num; tid++) {
int64_t timeValue = 0;
if (tid == timeID) { //
timeValue = timeInt;
file.write(reinterpret_cast<const char*>(&timeValue), sizeof(int64_t));
file.write(reinterpret_cast<const char*>(UArr), info.Height * info.Width * sizeof(double));
file.write(reinterpret_cast<const char*>(VArr), info.Height * info.Width * sizeof(double));
timeValue = 0;
}
else {
file.write(reinterpret_cast<const char*>(&timeValue), sizeof(int64_t));
for (int64_t i = 0; i < info.Height; i++) { // U
file.write(reinterpret_cast<const char*>(blockData.data()), info.Width * sizeof(double));
}
for (int64_t i = 0; i < info.Height; i++) { // V
file.write(reinterpret_cast<const char*>(blockData.data()), info.Width * sizeof(double));
}
}
}
}
else {}
// 移动到制定为
int64_t writeoffset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET
+ 3 * sizeof(int64_t)
+ LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER
+ sizeof(int64_t)
+ sizeof(double) * 6
+ LAMP_WIND_WINUV_NUM
+ int64_t(sizeof(int64_t) + int64_t(info.Width) * int64_t(info.Height) * sizeof(double) * 2) * timeID;
file.seekg(writeoffset, std::ios::beg);
file.write(reinterpret_cast<const char*>(&timeInt), sizeof(int64_t));
file.write(reinterpret_cast<const char*>(UArr), int64_t(info.Width)* int64_t(info.Height) * sizeof(double));
file.write(reinterpret_cast<const char*>(VArr), int64_t(info.Width)* int64_t(info.Height) * sizeof(double));
file.close();
}
return 0;
}