#include "pch.h" #include "IDWHelper.h" #include #include #include #include #include #include #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> 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 dataWellOnLayer; // 井点处层位与井的差值 vector dataWellSpace; size_t len = wellData.size(); for (size_t i = 0; i < len; i++) { array 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 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> 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 dataWellOnLayer; // 井点处层位与井的差值 vector dataWellSpace; size_t len = wellData.size(); for (size_t i = 0; i < len; i++) { array 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 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> 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 pCurves;// = new std::vector(); std::vector pLayers;// = new std::vector(); pMeshNew->ContourCreate(&pCurves, &pLayers, contourStep, contourMarkStep, strLayerMark, strLayerOther, zMin, zMax); AddContourCurve(&pCurves, &pLayers, posNew); vector::iterator it = pCurves.begin(); while (it != pCurves.end()) { delete *it; it = pCurves.erase(it); } vector::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* curves, std::vector* 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>& data, vector& 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 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; }