869 lines
24 KiB
C++
869 lines
24 KiB
C++
|
|
#include <QDateTime>
|
|||
|
|
#include <QTime>
|
|||
|
|
#include <QTextStream>
|
|||
|
|
#include <QTextCodec>
|
|||
|
|
#include "basefun.h"
|
|||
|
|
#include "memrdwt.h"
|
|||
|
|
#include "CStringType.h"
|
|||
|
|
#include "DepthProgress.h"
|
|||
|
|
#include "GeometryUtils.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];
|
|||
|
|
char Set[200];
|
|||
|
|
//for las
|
|||
|
|
CString DepthUnit;
|
|||
|
|
//for las3.0SBT
|
|||
|
|
float WaveStartTime[500];
|
|||
|
|
float WaveTimeRlev[500];
|
|||
|
|
Slf_FILE_MESSAGE *pFILE_MESSAGE;
|
|||
|
|
}ScanInf;
|
|||
|
|
struct CLine
|
|||
|
|
{
|
|||
|
|
CLine(char*pLine)
|
|||
|
|
{
|
|||
|
|
m_pLine=pLine;
|
|||
|
|
}
|
|||
|
|
public:
|
|||
|
|
char *replace(char *pOldChar,char *pNewChar)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
return m_pLine;
|
|||
|
|
}
|
|||
|
|
char*m_pLine;
|
|||
|
|
};
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
QTextCodec *codec = QTextCodec::codecForName("UTF8");
|
|||
|
|
char showName[80];
|
|||
|
|
sprintf(showName,"读%s数据",ScanInf.TexTypename);
|
|||
|
|
DepthProgress MyDepthProgress;
|
|||
|
|
MyDepthProgress.CreatProgress(0,100,showName);//"解编SLFAscii数据");
|
|||
|
|
MyDepthProgress.SetDepth(0);
|
|||
|
|
QFile InFile(FileName);
|
|||
|
|
char *pLine=new char[50000];
|
|||
|
|
if( !InFile.open(QIODevice::ReadOnly|QIODevice::Text ) )return 0;
|
|||
|
|
for(int i=0;i<HeadLineNum;i++){
|
|||
|
|
InFile.readLine(pLine,50000);
|
|||
|
|
QByteArray line=pLine;
|
|||
|
|
line=line.simplified();
|
|||
|
|
if(line=="")continue;
|
|||
|
|
QStringList strs=GetStringList(line);//,IsSpa,IsTab,IsCom,IsSem,DelDubSpa);
|
|||
|
|
strs.removeAll("");
|
|||
|
|
if(strs.size()==4&&strs[0]=="SET")
|
|||
|
|
{
|
|||
|
|
strcpy(ScanInf.Set,strs[2].toStdString().c_str());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#pragma region 判断是否为Forward转出的Las(深度单独一行,数据有换行)
|
|||
|
|
|
|||
|
|
QMap<QString,int> facs;
|
|||
|
|
if(!ScanInf.rlev&&stricmp(ScanInf.Set,"Dip")==0)
|
|||
|
|
{
|
|||
|
|
QString path=GetConfPath();
|
|||
|
|
path+="FRAC.CFG";
|
|||
|
|
FILE *fp1=fopen(path.toStdString().c_str(),"rt");
|
|||
|
|
if(fp1)
|
|||
|
|
{
|
|||
|
|
char s[100];
|
|||
|
|
int t[10];
|
|||
|
|
fscanf(fp1,"%s %s %s %s %s %s %s %s %s\n",s,s,s,s,s,s,s,s,s);
|
|||
|
|
while(!feof(fp1)){
|
|||
|
|
fscanf(fp1,"%d %s %d %d %d %d %d\n",&t[0],&s[0],&t[1],&t[2],&t[3],&t[4],&t[5]);
|
|||
|
|
facs[s]=t[0];
|
|||
|
|
}
|
|||
|
|
fclose(fp1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
BOOL IsForwardLas=0;
|
|||
|
|
//int pos=textstream.pos();//当textstream读到汉字时,pos函数停止工作
|
|||
|
|
float dep[10];
|
|||
|
|
int Row=0,DataRow;//DataRow 每个深度点数据行数
|
|||
|
|
int ilen=0;
|
|||
|
|
int dotsize=0;
|
|||
|
|
for(int i=0;i<ScanInf.dCurveNum;i++)dotsize+=ScanInf.DataPoint[i];
|
|||
|
|
while(!InFile.atEnd())
|
|||
|
|
{
|
|||
|
|
if(Row>=10)break;
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
QByteArray line=pLine;
|
|||
|
|
line=line.simplified();
|
|||
|
|
if(line=="")continue;
|
|||
|
|
QStringList StrList=GetStringList(line);//,IsSpa,IsTab,IsCom,IsSem,DelDubSpa);
|
|||
|
|
if(StrList.size()==0)continue;
|
|||
|
|
if(StrList.size()>1)
|
|||
|
|
{
|
|||
|
|
while(StrList.size()<dotsize+ScanInf.HaveDepth&&!InFile.atEnd())
|
|||
|
|
{
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
QByteArray line=pLine;
|
|||
|
|
// line=line.trimmed();
|
|||
|
|
line=line.simplified();
|
|||
|
|
if(line=="")continue;
|
|||
|
|
QStringList StrList1=GetStringList(line);
|
|||
|
|
StrList.append(StrList1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(StrList.size()==1)
|
|||
|
|
{
|
|||
|
|
DataRow=0;
|
|||
|
|
int Col=1;
|
|||
|
|
if(!Row)IsForwardLas=1;
|
|||
|
|
dep[Row++]=StrList[0].toFloat();
|
|||
|
|
while(!InFile.atEnd())
|
|||
|
|
{
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
line=line.simplified();
|
|||
|
|
if(line=="")continue;
|
|||
|
|
StrList=GetStringList(line);
|
|||
|
|
if(StrList.size()==0)continue;
|
|||
|
|
if(StrList.size()>1&&StrList.size()<ScanInf.dCurveNum+1)
|
|||
|
|
{
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
QByteArray line=pLine;
|
|||
|
|
QStringList StrList1=GetStringList(line);
|
|||
|
|
StrList.append(StrList1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Col+=StrList.size();
|
|||
|
|
DataRow++;
|
|||
|
|
if(Col>=Num)break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(IsForwardLas)
|
|||
|
|
{
|
|||
|
|
for(int i=1;i<10;i++)
|
|||
|
|
{
|
|||
|
|
if(dep[i]<dep[i-1]){AfxMessageBox("该数据可能不是标准的Forward Las数据,请检查后再解编");return 0;}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
InFile.seek(0);//(pos);
|
|||
|
|
for(int i=0;i<HeadLineNum;i++) {
|
|||
|
|
InFile.readLine(pLine,50000);//跳过文件头
|
|||
|
|
}
|
|||
|
|
#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(!InFile.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;
|
|||
|
|
}
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
QByteArray line=pLine;//codec->toUnicode(pLine,ilen);//.readLine();
|
|||
|
|
line=line.simplified();
|
|||
|
|
if(line=="")continue;
|
|||
|
|
QStringList StrList=GetStringList(line);
|
|||
|
|
if(StrList.size()==0)continue;
|
|||
|
|
if(StrList.size()>1)
|
|||
|
|
{
|
|||
|
|
while(StrList.size()<dotsize+ScanInf.HaveDepth&&!InFile.atEnd())
|
|||
|
|
{
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
QByteArray line=pLine;
|
|||
|
|
// line=line.trimmed();
|
|||
|
|
line=line.simplified();
|
|||
|
|
if(line=="")continue;
|
|||
|
|
QStringList StrList1=GetStringList(line);
|
|||
|
|
StrList.append(StrList1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(IsForwardLas)//Forward转出的Las(深度单独一行,数据有换行)
|
|||
|
|
{
|
|||
|
|
for(int i=0;i<DataRow;i++)
|
|||
|
|
{
|
|||
|
|
ilen=InFile.readLine(pLine,50000);
|
|||
|
|
line=pLine;
|
|||
|
|
line=line.simplified();
|
|||
|
|
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);
|
|||
|
|
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(ScanInf.rlev==0&&stricmp(ScanInf.Set,"Dip")==0)
|
|||
|
|
{
|
|||
|
|
int xx=facs.find(StrList[DataNum+j])==facs.end();
|
|||
|
|
if(!xx)
|
|||
|
|
{
|
|||
|
|
val=facs.find(StrList[DataNum+j]).value();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(_isnan(val))
|
|||
|
|
{
|
|||
|
|
val=-9999.;
|
|||
|
|
NanDataNum++;
|
|||
|
|
if(firstNanDataLine<0){
|
|||
|
|
firstNanDataLine=lineNum;
|
|||
|
|
firstNan=line;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
curvedata.find(CurveNames[k]).value().push_back(val);//val);
|
|||
|
|
}
|
|||
|
|
DataNum+=ScanInf.DataPoint[k];
|
|||
|
|
}
|
|||
|
|
lineNum++;
|
|||
|
|
}
|
|||
|
|
fclose(fpt);
|
|||
|
|
delete pLine;
|
|||
|
|
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,bool isinst)
|
|||
|
|
{
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
ScanInf.pFILE_MESSAGE->Xcoor=xCoord;
|
|||
|
|
ScanInf.pFILE_MESSAGE->Ycoor=yCoord;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
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);
|
|||
|
|
*/
|
|||
|
|
}
|
|||
|
|
if(!ScanInf.rlev)
|
|||
|
|
{
|
|||
|
|
QMap<QString,int> facs;
|
|||
|
|
QString path=GetConfPath();
|
|||
|
|
path+="FRAC.CFG";
|
|||
|
|
FILE *fp1=fopen(path.toStdString().c_str(),"rt");
|
|||
|
|
if(fp1)
|
|||
|
|
{
|
|||
|
|
char s[100];
|
|||
|
|
int t[10];
|
|||
|
|
fscanf(fp1,"%s %s %s %s %s %s %s %s %s\n",s,s,s,s,s,s,s,s,s);
|
|||
|
|
while(!feof(fp1)){
|
|||
|
|
fscanf(fp1,"%d %s %d %d %d %d %d\n",&t[0],&s[0],&t[1],&t[2],&t[3],&t[4],&t[5]);
|
|||
|
|
facs[s]=t[0];
|
|||
|
|
}
|
|||
|
|
fclose(fp1);
|
|||
|
|
}
|
|||
|
|
QString well;
|
|||
|
|
QStringList tablefield;
|
|||
|
|
tablefield<<"DEP";
|
|||
|
|
tablefield<<"AorX"; //XRMI_DYN_DipHeight
|
|||
|
|
tablefield<<"XETAorH";//XRMI_DYN_Azimuth
|
|||
|
|
tablefield<<"W";
|
|||
|
|
tablefield<<"DIPorS";//XRMI_DYN_Dip_APP
|
|||
|
|
tablefield<<"DIR";//XRMI_DYN_Azimuth
|
|||
|
|
tablefield<<"TDIP"; //真倾角 Dip_TRU
|
|||
|
|
tablefield<<"TDIR"; //真倾向 Azimuth
|
|||
|
|
tablefield<<"ID";//裂缝代码,type
|
|||
|
|
tablefield<<"NUM";
|
|||
|
|
|
|||
|
|
tablefield<<"X0";
|
|||
|
|
tablefield<<"Y0";
|
|||
|
|
tablefield<<"X1";
|
|||
|
|
tablefield<<"Y1";
|
|||
|
|
tablefield<<"X2";
|
|||
|
|
tablefield<<"Y2";
|
|||
|
|
tablefield<<"X3";
|
|||
|
|
tablefield<<"Y3";
|
|||
|
|
tablefield<<"X4";
|
|||
|
|
tablefield<<"Y4";
|
|||
|
|
tablefield<<"X5";
|
|||
|
|
tablefield<<"Y5";
|
|||
|
|
tablefield<<"X6";
|
|||
|
|
tablefield<<"Y6";
|
|||
|
|
tablefield<<"X7";
|
|||
|
|
tablefield<<"Y7";
|
|||
|
|
tablefield<<"X8";
|
|||
|
|
tablefield<<"Y8";
|
|||
|
|
tablefield<<"X9";
|
|||
|
|
tablefield<<"Y9";
|
|||
|
|
tablefield<<"X10";
|
|||
|
|
tablefield<<"Y10";
|
|||
|
|
tablefield<<"X11";
|
|||
|
|
tablefield<<"Y11";
|
|||
|
|
tablefield<<"X12";
|
|||
|
|
tablefield<<"Y12";
|
|||
|
|
tablefield<<"X13";
|
|||
|
|
tablefield<<"Y13";
|
|||
|
|
tablefield<<"X14";
|
|||
|
|
tablefield<<"Y14";
|
|||
|
|
tablefield<<"X15";
|
|||
|
|
tablefield<<"Y15";
|
|||
|
|
|
|||
|
|
QStringList tablefield1;
|
|||
|
|
tablefield1<<"DEPT";
|
|||
|
|
tablefield1<<"XRMI_DYN_DipHeight"; //
|
|||
|
|
tablefield1<<"XRMI_DYN_Azimuth";//
|
|||
|
|
tablefield1<<"W";
|
|||
|
|
tablefield1<<"XRMI_DYN_Dip_APP";//
|
|||
|
|
tablefield1<<"XRMI_DYN_Azimuth";//
|
|||
|
|
tablefield1<<"Dip_TRU"; //真倾角
|
|||
|
|
tablefield1<<"Azimuth"; //真倾向
|
|||
|
|
tablefield1<<"Type";//裂缝代码,type
|
|||
|
|
// tablefield1<<"NUM";
|
|||
|
|
|
|||
|
|
GetWellNameAndPath(FileName,well,path);
|
|||
|
|
if(stricmp(ScanInf.Set,"Dip")==0) {
|
|||
|
|
well="Frac_Hole.Table";
|
|||
|
|
}
|
|||
|
|
else well+="_TABLE";
|
|||
|
|
int iIndex=m_SlfFile.OpenTable(well.toStdString().c_str());
|
|||
|
|
if (iIndex < 0)
|
|||
|
|
{
|
|||
|
|
QString sname="DEP,";
|
|||
|
|
QString vtype="4,";
|
|||
|
|
QString vlen="4,";
|
|||
|
|
QString res="0,";
|
|||
|
|
int count=1;
|
|||
|
|
if(stricmp(ScanInf.Set,"Dip")==0)
|
|||
|
|
{
|
|||
|
|
for(int i=1;i<tablefield.size();i++)
|
|||
|
|
{
|
|||
|
|
sname+=tablefield[i];//.toUpper();
|
|||
|
|
vlen+="4";
|
|||
|
|
vtype+="4";
|
|||
|
|
res+="0";
|
|||
|
|
if(i!=tablefield.size()-1)
|
|||
|
|
{
|
|||
|
|
sname+=",";
|
|||
|
|
vlen+=",";
|
|||
|
|
vtype+=",";
|
|||
|
|
res+=",";
|
|||
|
|
}
|
|||
|
|
count++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
for(int i=0;i<ScanInf.dCurveNum;i++)
|
|||
|
|
{
|
|||
|
|
for(int j=0;j<ScanInf.DataPoint[i];j++)
|
|||
|
|
{
|
|||
|
|
sname+=OutCurve[i];
|
|||
|
|
if(ScanInf.DataPoint[i]>1) {
|
|||
|
|
sname+=QString::number(j);
|
|||
|
|
}
|
|||
|
|
count++;
|
|||
|
|
vlen+="4";
|
|||
|
|
vtype+="4";
|
|||
|
|
res+="0";
|
|||
|
|
//if(i!=ScanInf.dCurveNum-1)
|
|||
|
|
{
|
|||
|
|
sname+=",";
|
|||
|
|
vlen+=",";
|
|||
|
|
vtype+=",";
|
|||
|
|
res+=",";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
iIndex=m_SlfFile.Open_Set_Table(well.toStdString().c_str(),0,count,
|
|||
|
|
(char *)sname.toStdString().c_str(),
|
|||
|
|
(char *)vlen.toStdString().c_str(),
|
|||
|
|
(char *)vtype.toStdString().c_str(),
|
|||
|
|
(char *)res.toStdString().c_str());
|
|||
|
|
// AddTableToWellRound();
|
|||
|
|
}
|
|||
|
|
m_SlfFile.SetTableRecordCount(iIndex,line);//-nn);
|
|||
|
|
int len=m_SlfFile.GetTableRecordLength(iIndex);
|
|||
|
|
char *tabv=new char[len+1];
|
|||
|
|
int count=m_SlfFile.GetTableFieldCount(iIndex);
|
|||
|
|
Slf_TABLE_FIELD *f=new Slf_TABLE_FIELD[count];
|
|||
|
|
m_SlfFile.GetTableFieldInfo(iIndex,f);
|
|||
|
|
int c=md.size();//curvedata.find(CurveNames[0]).value().size();
|
|||
|
|
for(int i=0;i<c;i++)
|
|||
|
|
{
|
|||
|
|
int pos=0;
|
|||
|
|
memset(tabv,0,len);
|
|||
|
|
int add=0,oldadd=0,jj=0;
|
|||
|
|
for(int j=0;j<count;j++) {
|
|||
|
|
float yy=0;
|
|||
|
|
if(j==0) yy=md[i];
|
|||
|
|
else {
|
|||
|
|
int k=0;
|
|||
|
|
if(stricmp(ScanInf.Set,"Dip")==0)
|
|||
|
|
{
|
|||
|
|
if(j<tablefield1.size()){
|
|||
|
|
k=CurveNames.indexOf(tablefield1[j].toUpper());
|
|||
|
|
if(k>-1) {
|
|||
|
|
if(ScanInf.DataPoint[k]>1)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
else yy=curvedata.find(CurveNames[k]).value()[i];
|
|||
|
|
}
|
|||
|
|
else yy=0;
|
|||
|
|
}
|
|||
|
|
else yy=0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
k=j-add-1;
|
|||
|
|
if(k<0) {
|
|||
|
|
k=ScanInf.DataPoint[jj]+k;
|
|||
|
|
}
|
|||
|
|
yy=curvedata.find(CurveNames[jj]).value()[i*ScanInf.DataPoint[jj]+k];
|
|||
|
|
if(j>=add) {
|
|||
|
|
if(k) jj++;
|
|||
|
|
add+=ScanInf.DataPoint[jj];
|
|||
|
|
if(ScanInf.DataPoint[jj]<2&&!k) {
|
|||
|
|
jj++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
m_SlfFile.SetData(f[j].RepCode,&tabv[pos],&yy);
|
|||
|
|
pos+=f[j].Length;
|
|||
|
|
}
|
|||
|
|
m_SlfFile.WriteTable(iIndex,i+1,tabv);
|
|||
|
|
}
|
|||
|
|
delete f;
|
|||
|
|
delete tabv;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
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;
|
|||
|
|
float enddepth=outsdep+(int)((outedep-outsdep)/ScanInf.rlev+0.5)*ScanInf.rlev;
|
|||
|
|
int size=(enddepth-outsdep)/ScanInf.rlev+0.5+1;
|
|||
|
|
int hh=CurveNames.count();
|
|||
|
|
QStringList azims=GetSimilarCurves("AZIM");
|
|||
|
|
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();
|
|||
|
|
bool isAngle=false;//azims.indexOf(CurveNames[i])>-1);
|
|||
|
|
if(isinst)
|
|||
|
|
{
|
|||
|
|
if(ScanInf.DataPoint[i]==1)
|
|||
|
|
{
|
|||
|
|
for(int k=0;k<md.size();k++){
|
|||
|
|
m_SlfFile.WriteCurve(OutCurveNo[i],md[k],1,(float *)&_AryCurve[k]);
|
|||
|
|
}
|
|||
|
|
m_SlfFile.CloseCurve(OutCurveNo[i]);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
for(int k=0;k<md.size();k++)
|
|||
|
|
m_SlfFile.WriteWave(OutCurveNo[i],md[k],1,(float *)&_AryCurve[k]);
|
|||
|
|
m_SlfFile.CloseWave(OutCurveNo[i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
InstValue(outsdep,enddepth,md,_AryCurve,curAry,ScanInf.rlev,ScanInf.DataPoint[i],isAngle,0);
|
|||
|
|
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;
|
|||
|
|
}
|