logplus/tran/TexOutFun/TxtOutFun-1.cpp
2025-10-29 17:23:30 +08:00

685 lines
19 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <QDateTime>
#include <QTime>
#include <QTextStream>
#include "basefun.h"
QString cfg;
QList<double>dates;
QList<double>depths;
QList<QString>datest;
QList<QString>deptht;
double err=60;//2019.9.9 王卫让加
double ddep=0;
QStringList CurveNames;
qint64 DataLineNum;//数据行数
int HeadLineNum;//文件头行数
QMap<QString,vector<float> > curvedata;//curvedata--存放读入的曲线数据QMap原型为class QMap <K,T>,其中K表示键,T表示值,K和T属于映射关系.
vector<float> md;//存放深度
struct SCANINF
{
float stdep,endep,rlev;
short int dCurveNum;
int DataPoint[500],HaveDepth;
int LineDataPoint;
qint64 DataBeginPos;
char TexTypename[128];
//for las
CString DepthUnit;
//for las3.0SBT
float WaveStartTime[500];
float WaveTimeRlev[500];
}ScanInf;
QStringList GetStringList(QString line,BOOL IsSpa=1,BOOL IsTab=1,BOOL IsCom=1,BOOL IsSem=1,BOOL DelDubSpa=1)
{
if(!IsCom)line.replace(",","");//如果逗号不是分隔符,清除逗号
if(!IsSpa)line.replace(" ","");
else
{
//连续空格视为单个处理
if(DelDubSpa)while(line.indexOf(" ")>=0)line.replace(" "," ");
line=line.simplified();line.replace(" ",",");
}
if(!IsTab)line.replace(" ","");//tab
else line.replace(" ",",");
if(!IsSem)line.replace(";","");
else line.replace(";",",");
QStringList List=line.split(",");
return List;
}
int bSearch(FILE *fp,double*darray, int n, double data,double err)//
{
int low, mid, high;
if(darray == NULL) return -1;//
low = 0;
high = n - 1;
while(low <= high) {
mid = (low + high) / 2;
if(fabs(data-darray[mid])<err) {
if(fp&&mid+1<n) fprintf(fp,"id=%d %lf %lf %lf %s %s\n",mid,data,darray[mid],darray[mid+1],datest[mid].toStdString().c_str(),deptht[mid].toStdString().c_str());
return mid;
}
if(mid+1<n&&data>darray[mid]&&data<darray[mid+1]) {
if(fp) fprintf(fp,"id=%d %lf %lf %lf %s %s\n",mid,data,darray[mid],darray[mid+1],datest[mid].toStdString().c_str(),deptht[mid].toStdString().c_str());
return mid; //
}
else if(data < darray[mid]) high = mid - 1;
else low = mid + 1;
}
return -1;//
}
double ComputeDate(QStringList str)
{
double depth=0;
float a=0;
float b[7]={977616000,2678400,86400,3600,60,1,0};
QStringList ss,ss1;
int aa=0;
int bb=0;
for(int i=0;i<str.size();i++) {
ss1=str[i].split("/");
if(ss1.size()<2) {
ss1=str[i].split(":");
aa++;
}
else {
bb=ss1.size();
}
ss.append(ss1);
}
for(int k=3-bb;k<ss.size();k++) {
a=ss[k].toFloat();
depth+=a*b[k];
}
return depth;
}
int GetDepthS(char *FileName,QString cfg)
{
dates.clear();
depths.clear();
datest.clear();
deptht.clear();
QString dcfg=FileName;
int ic=dcfg.lastIndexOf("\\");
int ib=dcfg.lastIndexOf("/");
if(ib>ic) ic=ib;
cfg=cfg.remove("\n");
dcfg=dcfg.left(ic+1)+cfg;
char fname[200];
strcpy(fname,dcfg.toStdString().c_str());
FILE *fp=fopen(fname,"rt");
if(!fp)
{
CString sss;
sss.Format("打开时深转换文件%s失败请检查该文件是否存在\r\n否则将无法进行转换",fname);AfxMessageBox(sss);return 0;
}
char buf[1000];
buf[0]=0;
fgets(buf,1000,fp);
QString ss;
QStringList ss1,ss2;
while(!feof(fp))
{
if(!fgets(buf,1000,fp)) break;
ss=buf;
if(ss.indexOf("\t")>-1&&ss.indexOf(" ")>-1)
{
while(ss.indexOf(" ")>-1) ss.replace(" "," ");
ss.replace(" ","\t");
}
ss1=ss.split("\t");
if(ss1.size()<2) ss1=ss.split(",");
if(ss1.size()<2) ss1=ss.split(" ");
if(ss1.size()<2) continue;
ss2.clear();
ss2.append(ss1[0]);
ss2.append(ss1[1]);
dates.append(ComputeDate(ss2));
depths.append(ss1[2].toDouble());
datest.append(ss1[0]);
deptht.append(ss1[1]);
}
fclose(fp);
return dates.size();
}
//读取并检查数据行是否丢失数据列,或者个别行少数据(数据之间无间隔时会被当做缺失数据)
qint64 ReadAndCheckData(char *FileName,int Num)
{
char showName[80];
sprintf(showName,"读%s数据",ScanInf.TexTypename);
DepthProgress MyDepthProgress;
MyDepthProgress.CreatProgress(0,100,showName);//"解编SLFAscii数据");
MyDepthProgress.SetDepth(0);
QFile InFile(FileName);
if( !InFile.open(QIODevice::ReadOnly ) )return 0;
QTextStream textstream( &InFile );
for(int i=0;i<HeadLineNum;i++)QString lline=textstream.readLine();//跳过文件头
#pragma region 判断是否为Forward转出的Las深度单独一行数据有换行
BOOL IsForwardLas=0;
//int pos=textstream.pos();//当textstream读到汉字时pos函数停止工作
float dep[10];
int Row=0,DataRow;//DataRow 每个深度点数据行数
while(!textstream.atEnd())
{
if(Row>=10)break;
QString line=textstream.readLine();
line=line.simplified();
if(line=="")continue;
//QStringList StrList=line.split(" ");
QStringList StrList=GetStringList(line);//,IsSpa,IsTab,IsCom,IsSem,DelDubSpa);
if(StrList.size()==0)continue;
if(StrList.size()==1)
{
DataRow=0;
int Col=1;
if(!Row)IsForwardLas=1;
dep[Row++]=StrList[0].toFloat();
while(!textstream.atEnd())
{
line=textstream.readLine();
line=line.simplified();if(line=="")continue;
//StrList=line.split(" ");
StrList=GetStringList(line);
if(StrList.size()==0)continue;
Col+=StrList.size();
DataRow++;
if(Col>=Num)break;
}
}
}
if(IsForwardLas)
{
for(int i=1;i<10;i++)
{
if(dep[i]<dep[i-1]){AfxMessageBox("该数据可能不是标准的Las数据请检查后再解编");return 0;}
}
}
textstream.seek(0);//(pos);
for(int i=0;i<HeadLineNum;i++)QString lline=textstream.readLine();//跳过文件头
#pragma endregion 判断是否为Forward转出的Las深度单独一行数据有换行
qint64 lineNum=0,lostNum=0,firstLostNum=-1,colNum;//总数据行数,丢失数据的行数,首个丢失数据的行号,数据列数
QString firstLost;//第一个丢失数据行
int NanDataNum=0,firstNanDataLine=-1;//无效数据个数,第一个无效数据所在的数据行
QString firstNan;//第一个无效数据行
float depth;float first1=0;
QStringList ss;
QString tempfi=FileName;
QString wellname,path;
GetWellNameAndPath(tempfi,wellname,path);
QString temp=GetLogdataPath()+"temp";
CreateDir((char *)temp.toStdString().c_str());
tempfi=GetLogdataPath()+"temp\\"+wellname+".txt";
FILE *fpt=fopen(tempfi.toStdString().c_str(),"wt");
while(!textstream.atEnd())//for(int i=0;i<10;i++)
{
int pro=lineNum*100/DataLineNum;
if(pro%2==0)if(!(MyDepthProgress.SetDepth(pro)))
{
InFile.close();
return 0;
}
QString line=textstream.readLine();
line=line.simplified();
if(line=="")continue;
//QStringList StrList=line.split(" ");
QStringList StrList=GetStringList(line);
if(StrList.size()==0)continue;
if(IsForwardLas)//Forward转出的Las深度单独一行数据有换行
{
for(int i=0;i<DataRow;i++)
{
line=textstream.readLine();line=line.simplified();
//QStringList StrList1=line.split(" ");
QStringList StrList1=GetStringList(line);
for(int i=0;i<StrList1.size();i++)StrList.append(StrList1[i]);
}
}
if(StrList.size()!=Num)//丢失数据
{
colNum=StrList.size();
if(lostNum==0){
firstLostNum=lineNum+1;
firstLost=line;
}
lostNum++;
}
if(ScanInf.HaveDepth>2)
{
float depth=0;
float a=0;
float b[5]={86400,3600,60,1,0};
for(int k=0;k<ScanInf.HaveDepth;k++) depth+=StrList[k].toFloat()*b[k];
depth=depth/1000.0;
if(!first1) {
first1=depth;
}
depth=depth-first1+ScanInf.stdep;
}
else if(ScanInf.HaveDepth>1)
{
float d1=StrList[2].toFloat();
if(StrList.size()>10)
{
if(d1<0.25)continue;
}
ss.clear();
for(int k=0;k<ScanInf.HaveDepth;k++) ss.append(StrList[k]);
double depth1=ComputeDate(ss);
//2019.9.9 王卫让加
if(dates.size()) {
int pos=bSearch(NULL/*fpw*/,(double *)&dates[0],dates.size(),depth1,err);//1.0);
if(pos>-1) {
depth=depths[pos];
fprintf(fpt,"%g ",depth);
for(int i=ScanInf.HaveDepth;i<StrList.size();i++) {
float d1=StrList[i].toFloat();
fprintf(fpt,"%10.3f ",d1);
}
fprintf(fpt,"\n");
}
}
}
else if(ScanInf.HaveDepth)
{
depth=StrList[0].toFloat();
}
else
{
depth=ScanInf.stdep+lineNum*ScanInf.rlev;
}
md.push_back(depth);
int DataNum=ScanInf.HaveDepth;
for(int k=0;k<ScanInf.dCurveNum;k++)
{
for(int j=0;j<ScanInf.DataPoint[k];j++)
{
float val=-9999.;
if(DataNum+j<StrList.size())val=StrList[DataNum+j].toFloat();
if(_isnan(val))
{
val=-9999.;
NanDataNum++;
if(firstNanDataLine<0){
firstNanDataLine=lineNum;
firstNan=line;
}
}
curvedata.find(CurveNames[k]).value().push_back(val);
}
DataNum+=ScanInf.DataPoint[k];
}
lineNum++;
}
fclose(fpt);
if(lineNum+HeadLineNum>DataLineNum)AfxMessageBox("可能会丢失数据");
InFile.close();
if(lostNum==0&&NanDataNum==0)return lineNum;//没有丢失,也没有无效数据
QString mes,mes1;
if(NanDataNum)
{
mes1="文件中存在"+QString::number(NanDataNum)+"个无效数据\r\n第一个存在无效数据的行在第"+QString::number(firstNanDataLine);
mes1+="个数据行,数据内容为:\r\n";
mes1+=firstNan;
if(!lostNum)mes1+="\r\n\r\n是否继续解编?\r\n是-用-9999.0替代无效数据,继续解编\r\n否-退出解编";
else mes1+="\r\n\r\n\r\n";
}
if(lineNum==lostNum)//整列缺失
{
mes="丢失数据列,文件头中定义数据列为"+QString::number(Num)+",实际数据列为"+QString::number(colNum)+"\r\n";
mes+="\r\n是否继续解编?\r\n是-用-9999.0替代丢失数据,继续解编\r\n否-退出解编";
}
else if(lostNum)
{
mes="共有"+QString::number(lostNum)+"行丢失数据列\r\n第一个丢失数据的行在第"+QString::number(firstLostNum);
mes+="个数据行,数据内容为:\r\n";
mes+=firstLost;
mes+="\r\n\r\n是否继续解编?\r\n是-用-9999.0替代丢失数据,继续解编\r\n否-退出解编";
}
MyDepthProgress.DelProgress();
int yes=QMessageBox::information(NULL,"数据信息不完整",mes1+mes,QMessageBox::Yes|QMessageBox::No,QMessageBox::No);
if(yes==QMessageBox::Yes)return lineNum;//存在丢失数据,用-9999.0替代丢失数据
else return 0;//存在丢失数据,不解编
}
bool Tran(char *FileName,char *outfile,int *OutCurveNo,char **OutCurve,char **strChineseName,char **strUnit)
{
int image=0;
md.clear();
curvedata.clear();
QTime StartTime=QTime::currentTime();
//获取井坐标和输出深度信息
float xCoord,yCoord,outsdep,outedep;
char *p;
p=outfile;
int len=strlen(p)+1;
p+=len;
GetTranMes(p,&xCoord,&yCoord,&outsdep,&outedep);
if(outsdep<=-99999.)outsdep=ScanInf.stdep;
if(outedep<=-99999.)outedep=ScanInf.endep;
if(outsdep>outedep)
{
float temp=outsdep;
outsdep=outedep;
outedep=temp;
}
char showName[80];
//sprintf(showName,"解编%s数据",ScanInf.TexTypename);
DepthProgress MyDepthProgress;
MyDepthProgress.CreatProgress(0,100,"统计数据行数");//showName);//"解编SLFAscii数据");
MyDepthProgress.SetDepth(20);
#pragma region 统计数据行数
FILE *fp;
if((fp=fopen(FileName,"rb"))==NULL)return 0;
DataLineNum=0;
int LineLen=(ScanInf.LineDataPoint+1)*15;//预算行长
if(ScanInf.LineDataPoint+1<100)LineLen*=2;//数据量小时适当开大点保证LineLen>行长
char *buf=new char[LineLen+1];
while(!feof(fp)){
fgets(buf,LineLen,fp);
if(strstr(buf,"IMAGE=")) {
QString str=strstr(buf,"IMAGE=")+6;
image=str.toInt();
}
DataLineNum++;
}
fclose(fp);
delete buf;
#pragma endregion 统计数据行数
CurveNames.clear();
for(int i=0;i<ScanInf.dCurveNum;i++)
{
QString str = QString(QLatin1String(OutCurve[i]));
CurveNames.append(str);
}
vector<float > temp;
temp.reserve(DataLineNum);
md.reserve(DataLineNum);
for(int i=0;i<ScanInf.dCurveNum;i++)
{
//if(OutCurveNo[i]>-1)
{
if(ScanInf.DataPoint[i]==1)//is curve
{
curvedata.insert(CurveNames[i], temp);
}
else //is wave
{
vector<float > wtemp;
wtemp.reserve(DataLineNum*ScanInf.DataPoint[i]);
curvedata.insert(CurveNames[i], wtemp);
}
}
}
qint64 line=ReadAndCheckData(FileName,ScanInf.HaveDepth+ScanInf.LineDataPoint);
if(!line)return 0;//line=0-存在丢失数据,不解编,>0,数据行数(没有丢失,或者用-9999.0替代丢失数据)
CMemRdWt m_SlfFile(outfile);
if(m_SlfFile.mFile==NULL){return 0;}
Slf_CURVE myCurve;
Slf_WAVE myWave;
if(xCoord!=-99999&&yCoord!=-99999)
{
int index=m_SlfFile.FindObjectIndex("井基本信息");
int indexSTable=m_SlfFile.OpenSTATIC("井基本信息");
m_SlfFile.WriteTable(indexSTable,1,&WellStaticInfo);//inf);
m_SlfFile.CloseTable(indexSTable);
int indexDTable=m_SlfFile.OpenDYNAMIC("测井信息");
m_SlfFile.WriteTable(indexDTable,1,&WellDynamicInfo);//inf);
m_SlfFile.CloseTable(indexDTable);
}
sprintf(showName,"产生曲线");
MyDepthProgress.CreatProgress(0,ScanInf.dCurveNum,showName);
for(int i=0;i<ScanInf.dCurveNum;i++)
{
//sprintf(showName,"产生第%d条曲线%s共%d条",i+1,OutCurve[i],ScanInf.dCurveNum);
//MyDepthProgress.SetShowName(showName);
if(!(MyDepthProgress.SetDepth(i+1))) break;
if(OutCurveNo[i]>-1)
{
if(ScanInf.DataPoint[i]==1)//is curve
{
OutCurveNo[i]=m_SlfFile.OpenCurve(OutCurve[i]);
if(OutCurveNo[i]<0)
{
strcpy(myCurve.Name,OutCurve[i]);
strcpy(myCurve.AliasName,strChineseName[i]);
strcpy(myCurve.Unit,strUnit[i]);
strcpy(myCurve.AliasUnit,strUnit[i]);
myCurve.RepCode=4;
myCurve.CodeLen=4;
myCurve.MinValue=99999.0;
myCurve.MaxValue=-99999.0;
myCurve.StartDepth=outsdep;
myCurve.EndDepth =outedep;
myCurve.DepLevel =ScanInf.rlev;
strcpy(myCurve.DepthUnit,"m");
strcpy(myCurve.DepthHZUnit,"");
OutCurveNo[i]=m_SlfFile.OpenCurve((Slf_CURVE *)&myCurve);
}
}
else //is wave
{
OutCurveNo[i]=m_SlfFile.OpenWave(OutCurve[i]);
if(OutCurveNo[i]<0)
{
strcpy(myWave.Name,OutCurve[i]);
strcpy(myWave.AliasName,strChineseName[i]);
strcpy(myWave.Unit,strUnit[i]);
strcpy(myWave.AliasUnit,strUnit[i]);
myWave.RepCode=4;
myWave.CodeLen=4;
myWave.ArrayNum=1;
myWave.MinValue=99999.0;
myWave.MaxValue=-99999.0;
myWave.StartDepth=outsdep;
myWave.EndDepth =outedep;
myWave.DepLevel =ScanInf.rlev;
if(ScanInf.DepthUnit=="M"){
sprintf(myWave.DepthUnit,"M");
sprintf(myWave.DepthHZUnit,"");
}
else {
sprintf(myWave.DepthUnit,"FT");
sprintf(myWave.DepthHZUnit,"英尺");
}
//strcpy(myWave.DepthUnit,"m");
myWave.StartTime=ScanInf.WaveStartTime[i];//0;
myWave.TimeLevel=ScanInf.WaveTimeRlev[i];//1;
myWave.TimeSamples=image>0?image:ScanInf.DataPoint[i];
strcpy(myWave.TimeUnit,"US");
strcpy(myWave.TimeHZUnit,"微秒");
strcpy(myWave.TimeName,"Time\0");
strcpy(myWave.TimeHZName,"时间\0");
OutCurveNo[i]=m_SlfFile.OpenWave((Slf_WAVE *)&myWave);
}
}
}
}
sprintf(showName,"解编%s数据",ScanInf.TexTypename);
MyDepthProgress.SetShowName(showName);
// MyDepthProgress.SetDepth(0);
//插值并输出曲线数据
std::vector<float>curAry;
int size=(outedep-outsdep)/ScanInf.rlev+0.5+1;
int hh=CurveNames.count();
for(int i=0;i<CurveNames.count();i++)
{
if(i>hh)
{
hh=0;
}
//sprintf(showName,"解编第%d条曲线%s共%d条",i+1,OutCurve[i],ScanInf.dCurveNum);
//MyDepthProgress.SetShowName(showName);
if(!(MyDepthProgress.SetDepth(i+1))) break;
if(OutCurveNo[i]<0)continue;
std::vector<float> _AryCurve;
_AryCurve=curvedata.find(CurveNames[i]).value();
curAry.clear();
//curAry=_AryCurve;//不插值
float curdepth=outsdep,enddepth=outedep;
curAry.reserve(size*ScanInf.DataPoint[i]);
int index=0;
int indf=0;
int inde=0;
float depthf=curdepth;
float depthe=enddepth;
DWORD point=0;
while (curdepth<=enddepth)
{
if(index==md.size()-1)
{
while(curdepth<=enddepth)
{
float v=-9999.0;
curAry.push_back(v);
// curdepth+=rlev;浮点深度累加有误差改成double可消除误差但仍然缺失最后一个数据点
point++;
curdepth=outsdep+point*ScanInf.rlev;
}
break;
}
float depth1=md[index];
if(fabsf(curdepth-depth1)>=ScanInf.rlev) {
index++;
if (index>=md.size())
break;
if(md[index-1] < curdepth && md[index] > curdepth)//后步过界,回退
index--;
else if(curdepth<md[index-1]){
}
else {
if (index>=md.size())
break;
continue;
}
}
if(index+1>=md.size()) break;
float depth2=md[index+1];
float rate=0;
if(depth2==depth1) {
for(int n=0;n<ScanInf.DataPoint[i];n++)
{
float val0=_AryCurve[index*ScanInf.DataPoint[i]+n];
curAry.push_back(val0);
}
}
else {
rate=(curdepth-depth1)/(depth2-depth1);
for(int n=0;n<ScanInf.DataPoint[i];n++)
{
float val0=_AryCurve[index*ScanInf.DataPoint[i]+n];
float val1=_AryCurve[(index+1)*ScanInf.DataPoint[i]+n];
if(val0==-9999||val1==-9999)
{
float v=-9999.0;
curAry.push_back(v);
}
else
{
float v=val0+rate*(val1-val0);
curAry.push_back(v);
}
}
}
/*
if(curdepth>=depth1 &&curdepth<=depth2)
{
while(curdepth<=depth2)
{
float rate=(curdepth-depth1)/(depth2-depth1);
if(index+1>=_AryCurve.size()/ScanInf.DataPoint[i])
break;
for(int n=0;n<ScanInf.DataPoint[i];n++)
{
float val0=_AryCurve[index*ScanInf.DataPoint[i]+n];
float val1=_AryCurve[(index+1)*ScanInf.DataPoint[i]+n];
if(val0==-9999||val1==-9999)
{
float v=-9999.0;
curAry.push_back(v);
}
else
{
float v=val0+rate*(val1-val0);
curAry.push_back(v);
}
}
//curdepth+=rlev;
}
index++;
}
else
{
if(curdepth>depth2)
index++;
else
{
float v=-9999.0;
for(int n=0;n<ScanInf.DataPoint[i];n++) {
curAry.push_back(v);
}
//curdepth+=rlev;
}
}
*/
point++;
curdepth=outsdep+point*ScanInf.rlev;
while(curdepth>=depth2) {
index++;
if(index+1>=md.size()) break;
depth2=md[index+1];
}
if(index>=md.size()) break;
}
if(ScanInf.DataPoint[i]==1)
{
m_SlfFile.WriteCurve(OutCurveNo[i],outsdep,size,(float *)&curAry[0]);
m_SlfFile.CloseCurve(OutCurveNo[i]);
}
else
{
std::vector<float>curAry1;
std::vector<float>curAry2;
if(image) {
for(int j=0;j<size;j++){
curAry1.resize(image);
float dd=(float)image/ScanInf.DataPoint[i];
Resamples(&curAry[ScanInf.DataPoint[i]*j],&curAry1[0],ScanInf.DataPoint[i],image);
for(int k=0;k<image;k++) curAry2.push_back(curAry1[k]);
}
curAry=curAry2;
}
m_SlfFile.WriteWave(OutCurveNo[i],outsdep,size,(float *)&curAry[0]);
m_SlfFile.CloseWave(OutCurveNo[i]);
}
}
dates.clear();
depths.clear();
datest.clear();
deptht.clear();
m_SlfFile.Close();
md.clear();
curvedata.clear();
QTime EndTime=QTime::currentTime();
int elapsed = StartTime.msecsTo(EndTime);
int h=elapsed/1000/60/60;
int m=(elapsed-(h*1000*60*60))/1000/60;
int sec=(elapsed-(h*1000*60*60)-(m*1000*60))/1000;
int msec=elapsed-(h*1000*60*60)-(m*1000*60)-sec*1000;
QTime time(h,m,sec,msec);
QString Stime=QString::fromLocal8Bit("开始时间:")+StartTime.toString("hh:mm:ss.zzz");
Stime+=QString::fromLocal8Bit("\r\n结束时间:")+EndTime.toString("hh:mm:ss.zzz");
Stime+=QString::fromLocal8Bit("\r\n耗时:")+time.toString("hh:mm:ss.zzz");
Stime+=QString::fromLocal8Bit("\r\n")+QString::number(elapsed)+QString::fromLocal8Bit("毫秒");
//QMessageBox::about(NULL,QString::fromLocal8Bit("解编运行时间"),Stime);
return TRUE;
}