You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

714 lines
18 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "pch.h"
#include "IDWHelper.h"
#include <array>
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <omp.h>
#include "IDWCalculation.h"
#include "GridCalculate.h"
bool GetApplicationPath(CString* appPath)
{
char szDir[MAX_PATH];
GetModuleFileName(0, szDir, MAX_PATH);
int i;
i = lstrlen(szDir) - 1;
while (i > 0)
{
if (szDir[i] == _T('\\'))
{
szDir[i] = 0;
break;
}
i--;
}
sprintf_s(szDir, _T("%s\\GridModel.exe"), szDir);
*appPath = szDir;
return TRUE;
}
IDWHelper::IDWHelper()
{
m_pXy = nullptr;
m_pXyTmp = nullptr;
}
IDWHelper::~IDWHelper()
{
if (m_pXyTmp != nullptr)
{
delete m_pXyTmp;
m_pXyTmp = nullptr;
}
}
void IDWHelper::CalculateAdjustData(LPCTSTR layerFile, LPCTSTR wellFile, LPCTSTR outFile)
{
if (OpenFile(layerFile) == FALSE) {
return;
}
CPositionList posListMesh;
CMesh* pMesh;
int nCount = m_pXy->GetElement(DOUBLEFOX_MESH, posListMesh);
POSITION posMesh = NULL;
if (nCount > 0)
{
posMesh = posListMesh.GetHead();
pMesh = (CMesh*)m_pXy->GetAtValue(posMesh);
}
else {
return;
}
// 没有网格数据则退出
if (posMesh == nullptr) return;
std::string strWellFile = string(wellFile);
vector<array<double, 3>> wellData;
m_names.clear();
this->m_bWithName = TRUE;
ReadInToMatrix(strWellFile, wellData, m_names);
long numx, numy; pMesh->GetNumber(numx, numy);
double ddx, ddy; pMesh->GetDelt(ddx, ddy);
double x0, y0; pMesh->GetOrg(x0, y0);
double x1 = x0 + ddx * numx;
double y1 = y0 + ddy * numy;
// 井点处的层位Z值
vector<double> dataWellOnLayer;
// 井点处层位与井的差值
vector<double> dataWellSpace;
size_t len = wellData.size();
for (size_t i = 0; i < len; i++)
{
array<double, 3> arrCur = wellData[i];
double dValue = pMesh->GetValue(arrCur[0], arrCur[1]);
if (dValue > 1e30) {
dataWellOnLayer.push_back(InvalidZ);
dataWellSpace.push_back(InvalidZ);
continue;
}
double dSpace = dValue - arrCur[2];
if (dValue > 1e30)
{
dSpace = InvalidZ;
}
// TRACE("space:x=%lf, y=%lf, z=%lf, space=%lf\n", arrCur[0], arrCur[1], dValue, dSpace);
dataWellOnLayer.push_back(dValue);
dataWellSpace.push_back(dSpace); // 误差值
}
CString strLine;
// 误差文件,带井号
CStdioFile fwAdjust;
CString strFilAdjust = MakeExtFileName(outFile, "_adjust", ".csv");
if (!fwAdjust.Open(strFilAdjust, CFile::modeCreate | CFile::modeWrite))
{
return;
}
// 清理无效值
for (size_t i = 0; i < len; i++)
{
if (dataWellOnLayer[i] > 1e30)
{
continue;
}
//array<double, 3> nums = { 0 };
//nums[0] = wellData[i][0];
//nums[1] = wellData[i][1];
//nums[2] = dataWellSpace[i];
strLine.Format("%s,%f,%f,%f,%f,%f\n", m_names[i], wellData[i][0], wellData[i][1], wellData[i][2], dataWellOnLayer[i], dataWellSpace[i]);
fwAdjust.WriteString(strLine);
}
fwAdjust.Close();
}
bool IDWHelper::Calculate(CMesh* pMesh, vector<array<double, 3>> wellData
, CMesh* pMeshNew, LPCTSTR outFile, double factor, LPCTSTR faultLayer
,int times, int gridM, int smooth)
{
CString strAppPath(_T(""));
GetApplicationPath(&strAppPath);
if (GetFileAttributes(strAppPath) < 0)
{
AfxMessageBox(_T("ERROR运算模块不存在"));
return false;
}
//AfxMessageBox(strAppPath);
long numx, numy; pMesh->GetNumber(numx, numy);
double ddx, ddy; pMesh->GetDelt(ddx, ddy);
double x0, y0; pMesh->GetOrg(x0, y0);
double x1 = x0 + ddx * numx;
double y1 = y0 + ddy * numy;
if (gridM == 0) {
gridM = numx;
}
// 井点处的层位Z值
vector<double> dataWellOnLayer;
// 井点处层位与井的差值
vector<double> dataWellSpace;
size_t len = wellData.size();
for (size_t i = 0; i < len; i++)
{
array<double, 3> arrCur = wellData[i];
//long iX = AfxGetPublicFunction()->FloatToLong((arrCur[0] - x0) / ddx);
//long iY = AfxGetPublicFunction()->FloatToLong((arrCur[1] - y0) / ddy);
//// 无效值
//if (iX < 0 || iX >= numx || iY < 0 || iY >= numy) {
// dataWellOnLayer.push_back(InvalidZ);
// dataWellSpace.push_back(InvalidZ);
// continue;
//}
//double dValue = pMesh->GetValue(iX, iY);
double dValue = pMesh->GetValue(arrCur[0], arrCur[1]);
if (dValue > 1e30) {
dataWellOnLayer.push_back(InvalidZ);
dataWellSpace.push_back(InvalidZ);
continue;
}
double dSpace = dValue - arrCur[2];
if (dValue > 1e30)
{
dSpace = InvalidZ;
}
//TRACE("space:x=%lf, y=%lf, z=%lf, space=%lf\n", arrCur[0], arrCur[1], dValue, dSpace);
dataWellOnLayer.push_back(dValue);
dataWellSpace.push_back(dSpace); // 误差值
}
CString strLine;
CString strFileXyz = MakeExtFileName(outFile, "_tmp.xyz");
CStdioFile fwXyz;
// 误差文件,带井号
CStdioFile fwAdjust;
if (this->m_bWithName)
{
CString strFilAdjust = MakeExtFileName(outFile, "_adjust", ".csv");
fwAdjust.Open(strFilAdjust, CFile::modeCreate | CFile::modeWrite);
}
if (fwXyz.Open(strFileXyz, CFile::modeCreate | CFile::modeWrite) == FALSE)return false;
int nValidCount = 0;
// 清理无效值
for (size_t i = 0; i < len; i++) {
if (dataWellOnLayer[i] > 1e30)
{
continue;
}
array<double, 3> nums = { 0 };
//long iX = AfxGetPublicFunction()->FloatToLong((wellData[i][0] - x0) / ddx);
//long iY = AfxGetPublicFunction()->FloatToLong((wellData[i][1] - y0) / ddy);
//nums[0] = iX;
//nums[1] = iY;
//nums[2] = dataWellSpace[i];
nums[0] = wellData[i][0];
nums[1] = wellData[i][1];
nums[2] = dataWellSpace[i];
// 仅写不在断层内的点
if (!IsPointInFault(nums[0], nums[1], faultLayer) && abs(nums[2]) < 1E20)
{
strLine.Format("%f,%f,%f\n", nums[0], nums[1], nums[2]);
fwXyz.WriteString(strLine);
}
if (this->m_bWithName)
{
strLine.Format("%s,%f,%f,%f,%f,%f\n", m_names[i], wellData[i][0], wellData[i][1], wellData[i][2], dataWellOnLayer[i], dataWellSpace[i]);
// strLine.Format("%s,%f,%f,%f,%f\n", m_names[i], nums[0], nums[1], wellData[i][2], nums[2]);
fwAdjust.WriteString(strLine);
}
nValidCount++;
}
fwXyz.Close();
if (this->m_bWithName)
{
fwAdjust.Close();
}
if (nValidCount == 0)
{
return false;
}
CString strBoundFile = MakeExtFileName(outFile, "_border.dfd");
CStdioFile fw;
if (fw.Open(strBoundFile, CFile::modeCreate | CFile::modeWrite) == FALSE)return false;
fw.WriteString(_T("Layer M 边界\n"));
fw.WriteString(_T("Pline\n"));
strLine.Format("%f,%f\n", x0, y0);
fw.WriteString(strLine);
strLine.Format("%f,%f\n", x0, y1);
fw.WriteString(strLine);
strLine.Format("%f,%f\n", x1, y1);
fw.WriteString(strLine);
strLine.Format("%f,%f\n", x1, y0);
fw.WriteString(strLine);
strLine.Format("%f,%f\n", x0, y0);
fw.WriteString(strLine);
fw.WriteString("\n");
fw.Close();
CString strFileAdjust = MakeExtFileName(outFile, "_tmp.f(x,y)");
CString strParameter;
strParameter.Format(_T("\"%s\" \"%s\" %d \"%s\" \"%s\" %d %d %d")
, strFileXyz, strFileAdjust, times
, strBoundFile // 边界
, "NULL" // 断层
, gridM, smooth, 0); // 断层优先级
// 执行网格化
SHELLEXECUTEINFO ShExecInfo = { 0 };
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = strAppPath;
ShExecInfo.lpParameters = strParameter;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
// 用差值网格进行校正
//if (OpenFile(strFileAdjust) == FALSE) {
// return;
//}
CMesh* pMeshAdjust = ReadFileMesh(strFileAdjust);
long numxA, numyA;
pMeshAdjust->GetNumber(numxA, numyA);
// CMesh* pMeshNew = new CMesh();
GridCalculate gridCalculate;
if (pMeshNew == nullptr) {
pMeshNew = new CMesh;
}
gridCalculate.CaculateMesh(pMesh, pMeshAdjust, pMeshNew, 0, 1, 0);
return true;
/*
// 反距离加权运算
CGrid* pGrd = (pMesh->GetMesh());
IDWCalculation idw;
idw.m_factor = factor;
idw.SetData(vecValidSpace);
int nStep = 0;
//#pragma omp parallel for
for (int i = 0; i < numx; i++)
{
for (int j = 0; j < numy; j++)
{
double dValueInter = 0, dValueResult = 0, dValueBefore = 0;
dValueBefore = pMesh->GetValue(i, j);
if (!pMesh->IsInRangeZ(dValueBefore)) {
pGrd->SetValue(i, j, InvalidZ);
continue;
}
//TRACE("\ndValueBefore:x=%d, y=%d, z=%lf", i, j, dValueBefore);
if (dValueBefore > 1e30) {
dValueBefore = InvalidZ;
continue;
}
// 计算矫正量
dValueInter = idw.GetValue(i, j);
dValueResult = dValueBefore - dValueInter;
//TRACE(" z=%lf, space=%lf", dValueResult, dValueInter);
//#pragma omp critical
pGrd->SetValue(i, j, dValueResult);
//m_pMesh->SetZ(i, j, dValueResult);
}
if (DoProgress != nullptr) {
DoProgress(_T("数据校正"), (int)((++nStep)/ (numx*1.0)*100.0));
}
}
((CDimension2D*)pGrd)->GetRange();*/
}
//class TestCAdapter
//{
//private:
// IDWHelper *t;
//public:
// TestCAdapter(IDWHelper *t_) :t(t_) {}
// void operator()(CCurve *curve, CString strLayer)
// {
// t->AddContourCurve(curve, strLayer);
// }
//};
//typedef POSITION(*pmfn1)(CCurve* pCurve, CString strLayer);
void IDWHelper::Calculate(LPCTSTR layerFile, LPCTSTR wellFile, LPCTSTR outFile, double factor,
LPCTSTR faultLayer, double contourStep/* = 5.0*/, int contourMarkStep/* = 5*/
,int times, int gridM, int smooth, BOOL withName /*= FALSE*/)
{
m_bWithName = withName;
// 打开文件
if (OpenFile(layerFile) == FALSE) {
return;
}
CPositionList posListMesh;
CMesh* pMesh;
int nCount = m_pXy->GetElement(DOUBLEFOX_MESH, posListMesh);
POSITION posMesh = NULL;
if (nCount > 0)
{
posMesh = posListMesh.GetHead();
pMesh = (CMesh*)m_pXy->GetAtValue(posMesh);
}
else {
return;
}
if (posMesh == nullptr) return;
CLayer* pLayer = m_pXy->GetAtLayer(posMesh);
std::string strWellFile = string(wellFile);
vector<array<double, 3>> wellData;
ReadInToMatrix(strWellFile, wellData, m_names);
CMesh* pMeshNew = nullptr;
pMeshNew = new CMesh;
if (Calculate(pMesh, wellData, pMeshNew, outFile, factor, faultLayer, times, gridM, smooth) == false) {
if (m_pXy != nullptr)
{
delete m_pXy;
m_pXy = nullptr;
}
return;
}
POSITION posNew = m_pXy->InsertElementAfter(posMesh, pMeshNew, DOUBLEFOX_MESH);
m_pXy->SetElementLayer(posNew, pLayer);
m_pXy->SetCurrentLayer(pLayer);
m_pXy->RemoveAt(posMesh);
double zMin = pMeshNew->GetMesh()->range[0];
double zMax = pMeshNew->GetMesh()->range[1];
// 删除已有等值线图层的图元
CPositionList list;
m_pXy->GetElement("Layer:\\等值线", list, TRUE);
for (POSITION pos = list.GetHeadPosition(); pos != nullptr; list.GetNext(pos))
{
m_pXy->RemoveAt(list.GetAt(pos));
}
//double contourStep = 5.0;
//long contourMarkStep = 5;
CString strLayerMark("");
CString strLayerOther("");
if (strLayerMark.IsEmpty()) strLayerMark = _T("Layer:\\等值线\\标注");
if (strLayerOther.IsEmpty()) strLayerOther = _T("Layer:\\等值线\\无标注");
CString curLayerName = m_pXy->GetCurrentLayer()->GetPathName();
CLayer* pMarkLayer = m_pXy->FindAddLayer(strLayerMark);
CLayer* pOtherLayer = m_pXy->FindAddLayer(strLayerOther);
if (pMarkLayer == NULL)
{
pMarkLayer = m_pXy->FindAddLayer(strLayerMark);
pMarkLayer->HowToViewCurve = new CHowToViewCurve();
pMarkLayer->HowToViewCurve->EnableDrawSourceCurve(FALSE);
CCurveInName* pInName = new CCurveInName();
CRect8 rect = pMeshNew->GetRect();
pInName->text_h = rect.Width() / 300;
pInName->m_size.cx = pInName->text_h*0.06;
pMarkLayer->HowToViewCurve->Add(pInName);
}
if (pOtherLayer == NULL)
{
pOtherLayer = m_pXy->FindAddLayer(strLayerOther);
pOtherLayer->HowToViewCurve = new CHowToViewCurve();
pOtherLayer->HowToViewCurve->EnableDrawSourceCurve(FALSE);
CCurveProperties* pview = new CCurveProperties();
pview->color = RGB(0, 0, 0);
pOtherLayer->HowToViewCurve->Add(pview);
}
// 设置断层
CDimension3D* pDfg = (CDimension3D*)pMeshNew->GetMesh();
pDfg->CDimensionBase::EmptyLink();//清空已有的断层信息
{
CCurveEx* pCurve;
COne* pOne;
CPositionList select;
if (m_pXy->GetElement(faultLayer, select, FALSE) > 0)
{
POSITION pt;
POSITION pos = select.GetHeadPosition();
while (pos)
{
pt = select.GetNext(pos);
pOne = m_pXy->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) continue;
pCurve = (CCurveEx*)pOne->GetValue();
pDfg->Faultage(*(CCurve*)pCurve);
}
}
}
// 生成新等值线
std::vector<CCurve*> pCurves;// = new std::vector<CCurve *>();
std::vector<CString*> pLayers;// = new std::vector<CString *>();
pMeshNew->ContourCreate(&pCurves, &pLayers, contourStep, contourMarkStep, strLayerMark, strLayerOther, zMin, zMax);
AddContourCurve(&pCurves, &pLayers, posNew);
vector<CCurve *>::iterator it = pCurves.begin();
while (it != pCurves.end())
{
delete *it;
it = pCurves.erase(it);
}
vector<CString *>::iterator itL = pLayers.begin();
while (itL != pLayers.end())
{
delete *itL;
itL = pLayers.erase(itL);
}
//delete pCurves;
//pCurves = nullptr;
//delete pLayers;
//pLayers = nullptr;
// 已经被清除
//if (pMeshNew != nullptr) {
// delete pMeshNew;
// pMeshNew = nullptr;
//} // 保存
m_pXy->SaveAsWithExtension(outFile);
if (m_pXy != nullptr)
{
delete m_pXy;
m_pXy = nullptr;
}
}
void IDWHelper::AddContourCurve(std::vector<CCurve*>* curves, std::vector<CString*>* layer, POSITION newMeshPosition)
{
for (size_t i = 0; i < curves->size(); i++)
{
CCurve* pCurve = curves->at(i);
if (pCurve == NULL) continue;
CString* pName = layer->at(i);
CCurveEx *ce = new CCurveEx(pCurve->num);
for (int i = 0; i < ce->num; i++)
{
ce->x[i] = pCurve->x[i];
ce->y[i] = pCurve->y[i];
ce->z[i] = pCurve->z[i];
}
ce->nPoint = pCurve->nPoint;
ce->GetLocation();
if (pCurve->name)
ce->SetName(pCurve->name);
POSITION pos = m_pXy->InsertElementAfter(newMeshPosition, ce, DOUBLEFOX_CURVE);
m_pXy->SetElementLayer(pos, *pName);
}
}
void IDWHelper::ReadInToMatrix(string FilePath, vector<array<double, 3>>& data, vector<CString>& names)
{
ifstream in;
in.open(FilePath, ios::in);//打开一个file
if (!in.is_open()) {
//cout << "Can not find " << FilePath << endl;
system("pause");
}
int nDim = 3;
if (this->m_bWithName)
{
nDim = 4;
}
// 以‘,’为分隔符拆分字符串
char seps[] = " ,\t\n";
string buff;
while (getline(in, buff)) {
array<double, 3> nums = { 0 };
// string->char *
char *s_input = (char *)buff.c_str();
char *token = strtok(s_input, seps);
double a;
int i = 0;//行数i
while (token != NULL) {
a = atof(token);
nums[i] = a;
i++;
if (i > 2) break;
token = strtok(NULL, seps);
} // end while
// 数据行不符合要求
if (i < 3) continue;
// 读名称
if (this->m_bWithName)
{
token = strtok(NULL, seps);
CString strName;
strName = CA2CT(token);
names.push_back(strName);
}
data.push_back(nums);
}//end while
in.close();
//cout << "get data" << endl;
}
BOOL IDWHelper::OpenFile(LPCTSTR lpszFileName)
{
if (m_pXy != nullptr) {
m_pXy->Clear();
}
if (m_pXy == nullptr)
m_pXy = new CXy;
m_pXy->m_bRealTimeDraw = false;
if (m_pXy->ReadOtherWithExtension(lpszFileName))
{
return TRUE;
}
CFile file;
if (file.Open(lpszFileName, CFile::modeRead))
{
//m_FileName = lpszFileName;
CArchive ar(&file, CArchive::load);
Serialize(ar, m_pXy);
ar.Close();
}
file.Close();
return TRUE;
}
CMesh* IDWHelper::ReadFileMesh(LPCTSTR lpszFileName)
{
if (m_pXyTmp != nullptr) {
m_pXyTmp->Clear();
}
if (m_pXyTmp == nullptr)
m_pXyTmp = new CXy;
m_pXyTmp->m_bRealTimeDraw = false;
if (!m_pXyTmp->ReadOtherWithExtension(lpszFileName))
{
CFile file;
if (file.Open(lpszFileName, CFile::modeRead))
{
CArchive ar(&file, CArchive::load);
Serialize(ar, m_pXyTmp);
ar.Close();
}
file.Close();
}
CPositionList posListMesh;
CMesh* pMeshAdjust;
int nCount = m_pXyTmp->GetElement(DOUBLEFOX_MESH, posListMesh);
POSITION posMesh = NULL;
if (nCount > 0)
{
posMesh = posListMesh.GetHead();
pMeshAdjust = (CMesh*)m_pXyTmp->GetAtValue(posMesh);
}
else {
return nullptr;
}
return pMeshAdjust;
}
void IDWHelper::Serialize(CArchive& ar, CXy* pXy)
{
if (ar.IsStoring()) {}
else
{
if (pXy == nullptr) pXy = new CXy;
//BeginProgress(IDS_STRING_OpenFile);
CString name = ar.GetFile()->GetFileName();
name.MakeLower();
CSplitPath sp(name);
CString ext = sp.GetExtension();
//ar.m_pDocument = this; // set back-pointer in archive
if (ext == _T(".dfb") ||
ext == _T(".dft"))
{
pXy->m_version = pXy->DFB_ReadVersion(ar);
pXy->DFB_ReadEncrypt(ar, pXy->m_version);
if (pXy->IsEncrypted()) {
}
pXy->DFB_Serialize(ar, pXy->m_version);
}
else if (ext == ".dml" || ext == ".xml")
pXy->DML_Read2(*(ar.GetFile()));
else if (ext == ".pcg")
pXy->PCG_Read2(*(ar.GetFile()));
else
pXy->DFD_Read2(*(ar.GetFile()));
}
}
CString IDWHelper::MakeExtFileName(LPCTSTR oldFile, LPCTSTR newExt)
{
char strFileXyz[_MAX_PATH];
//char path[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
errno_t err;
err = _splitpath_s(oldFile, drive,
_MAX_DRIVE, dir, _MAX_DIR, fname,
_MAX_FNAME, ext, _MAX_EXT);
err = _makepath_s(
strFileXyz, _MAX_PATH,
drive, dir, fname, newExt);
return strFileXyz;
}
CString IDWHelper::MakeExtFileName(LPCTSTR oldFile,LPCTSTR nameSuffix, LPCTSTR newExt)
{
char strFileXyz[_MAX_PATH];
//char path[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
errno_t err;
err = _splitpath_s(oldFile, drive,
_MAX_DRIVE, dir, _MAX_DIR, fname,
_MAX_FNAME, ext, _MAX_EXT);
strcat(fname, nameSuffix);
err = _makepath_s(
strFileXyz, _MAX_PATH,
drive, dir, fname, newExt);
return strFileXyz;
}
BOOL IDWHelper::IsPointInFault(double x, double y, CString faultLayer)
{
CCurveEx* pCurve;
COne* pOne;
CPositionList select;
if (m_pXy->GetElement(faultLayer, select, FALSE) > 0)
{
POSITION pt;
POSITION pos = select.GetHeadPosition();
while (pos)
{
pt = select.GetNext(pos);
pOne = m_pXy->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) continue;
pCurve = (CCurveEx*)pOne->GetValue();
if (!pCurve->IsScope())
{
continue;
}
if (pCurve->IsInside(x, y)) {
return TRUE;
}
}
}
return FALSE;
}