#include "StdAfx.h" #include "itemmesh.h" #include "SigmaView.h" #include "DCHelp.h" #include "String.h" #include "ActionListItem.h" #include "ActionBackupItem.h" #include "MeshGenerationBorder.h" #include "ActionAddItem.h" #include wchar_t * AsciiToUnicodeChar(const char * str); static void Kit_StringTool_Split(const std::string & s, std::vector & tokens, const std::string & delimiters); //BOOL IsVisible(CWnd* pWnd); CItemMesh::CItemMesh(CSigmaDoc * ppDoc) : CItem(ppDoc) , m_smthtimes(0) , m_smoothcoef(0.0) { SetType(ITEM_MESH); m_bRuler = TRUE; m_nSelect = MESH_DEFAULT; pDrawerDC = nullptr; typeIndex = 0; m_levelAlpha = 0; modeFun = 0; m_nDimensionSel = 0; m_RulerIdea = 0; m_contourStep = 20; m_contourMarkStep = 5; m_strLayerMark = _T("Layer:\\Contour\\Mark"); m_strLayerOther = _T("Layer:\\Contour\\Other"); m_nFaultageMode = 0; m_strFaultageFile = _T(""); m_strFaultageLayer = _T(""); m_bDrawPrevPoint = FALSE; //m_pHistogramDlg = NULL; m_bDrawRangeZ = FALSE; m_bShowColorPane = FALSE; //CMainFrame* pmf = (CMainFrame*)GetDoc()->GetMainFrame(); //if (pmf)m_bShowColorPane = IsVisible(&(pmf->m_paneColorRuler)); } CItemMesh::~CItemMesh(void) { if (m_nSelect == MESH_EDIT_NODE) { //GetDoc()->Invalidate(); } /*if (!m_bShowColorPane) { CMainFrame* pmf = (CMainFrame*)GetDoc()->GetMainFrame(); if (pmf)pmf->ClosePane(COMMAND_BAR_COLOR_BAR); }*/ } void CItemMesh::SetPos(POSITION pos) { CItem::SetPos(pos); //CMainFrame* pmf = (CMainFrame*)GetDoc()->GetMainFrame(); /*if (pmf != NULL && pos != NULL) { CMesh* pValue = GetMesh(); if (pValue) { pmf->m_colorBar = pValue->color; pmf->m_paneColorRuler.Invalidate(); pmf->ShowPane(COMMAND_BAR_COLOR_BAR); } }*/ } //BOOL CItemMesh::InitPropertyGrid(CXTPPropertyGrid& grid) //{ // ////////////////////////////////////////////////////////////////////////////////////////////////// // //生成等值线的属性 // switch (m_nSelect) // { // case MESH_CREATE_CONTOUR: // return InitPropertyGridForContour(grid); // case MESH_GET_RANGE: // return InitPropertyGridGetRangeZ(grid); // case MESH_GRID_SMOOTH: // return InitPropertyGridSmooth(grid); // default: // return InitPropertyGridMesh(grid); // } // return TRUE; //} /*BOOL CItemMesh::OnGridItemChangeValue(CXTPPropertyGridItem* pItem) { switch (m_nSelect) { case MESH_CREATE_CONTOUR: return OnGridItemChangeValueForContour(pItem); case MESH_GET_RANGE: break; default: return OnGridItemChangeValueMesh(pItem); } return FALSE; }*/ //BOOL CItemMesh::InitPropertyGridGetRangeZ(CXTPPropertyGrid& grid) //{ // CPropertyGridItemAdd ItemAdd(NULL); // CXTPPropertyGridItem* pItem = grid.AddCategory(IDS_STRING_MESH); // ItemAdd.SetItem(pItem); pItem->Expand(); // COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); // CMesh* pValue = (CMesh*)pOne->GetValue(); // CString strFormat = GetFloatFormatString(); // m_szInvalidateValueZ.SetSize(-99999999, 99999999); // ItemAdd.AddItemSize8(IDS_STRING_INVALIDATE_Z, m_szInvalidateValueZ, &m_szInvalidateValueZ, IDS_STRING_MESH_CONTOUR_MIN, IDS_STRING_MESH_CONTOUR_MAX); // m_bResetZ = TRUE; // ItemAdd.AddItemBool(IDS_GI_TEXT_EDIT_UPDATE_COLOR, m_bResetZ, &m_bResetZ); // return TRUE; //} /* BOOL CItemMesh::InitPropertyGridMesh(CXTPPropertyGrid& grid) { ////////////////////////////////////////////////////////////////////////////////////////////////// //曲面属性 CPropertyGridItemAdd ItemAdd(NULL); CXTPPropertyGridItem* pItem = grid.AddCategory(IDS_STRING_MESH); ItemAdd.SetItem(pItem); pItem->Expand(); COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); CMesh* pValue = (CMesh*)pOne->GetValue(); CString strFormat = GetFloatFormatString(); //文件名称 DWORD nType = pValue->GetMeshType(); name = pValue->GetName(); CString strFilter = _T("DoubleFox Files (*.dfg;*.fxy;*.f(x,y))|*.dfg;*.fxy;*.f(x,y)|All Files (*.*)|*.*||"); pItem = ItemAdd.AddItemFileBox(TRUE, IDS_STRING_FILE_NAME, NULL, name, &name, strFilter, FALSE); //pItem->SetReadOnly(TRUE); pItem = ItemAdd.AddItemLong(IDS_GI_MESH_TIMES, pValue->m_nTimes, NULL//&pValue->m_nTimes); color = pValue->color; CCustomItemMeshColor* pItemMeshColor = new CCustomItemMeshColor(IDS_GI_COLOR, &color); pItemMeshColor->EnableWizardMode(FALSE); pItemMeshColor->m_pMeshForApply = pValue; ItemAdd.AddItem(pItemMeshColor); switch (pValue->GetTransparentMode()) { case IMAGE_TRANSPARENT_ALPHA: typeIndex = 1; break; //透明度 case IMAGE_TRANSPARENT_COLOR: typeIndex = 2; break; //透明颜色 default: typeIndex = 0; break; //原始 } ItemAdd.AddItemCombo(IDS_STRING_TRANSPARENT, IDS_TRANSPARENT_MODE, typeIndex, &typeIndex); //显示方式 m_levelAlpha = pValue->GetTransparentColor(); pItem = ItemAdd.AddItemLong(ID_IMAGE_TRANSPARENT_COLOR, m_levelAlpha, &m_levelAlpha); //透明度 pItem->SetReadOnly(!typeIndex); modeFun = GetFunctionIdea(pValue->GetMeshFunction()); pItem = ItemAdd.AddItemCombo(IDS_GI_MESH_FUNCTION, IDS_GI_MESH_FUNCTION_MODE, modeFun, &modeFun); //处理方式 if (pValue->GetMeshType() == MESH_FUN_2D) pItem->SetReadOnly(TRUE); //Z值范围 m_zrange.SetSize(0, 0); pValue->GetM(m_zrange.cx, m_zrange.cy); pItem = ItemAdd.AddItemSize8(IDS_STRING_ZRANGE, m_zrange, &m_zrange, IDS_STRING_MINIMUM, IDS_STRING_MAXIMAL); if (pValue->GetMeshFunction() != 0) pItem->SetReadOnly(TRUE); pItem->SetFlags(pItem->GetFlags() | xtpGridItemHasExpandButton); //设置按钮,为了可以根据人工定制的 ((CCustomItemPoint*)pItem)->SetItem(this); //为了可以触发按钮按下的事件 //坐标 m_point.SetPoint(pValue->left, pValue->bottom); pItem = ItemAdd.AddItemPoint(IDS_GI_COORDINATE, m_point, &m_point); pItem->SetReadOnly(TRUE); if (pValue->m_pImage) { pItem = ItemAdd.AddItemSize8(IDS_STRING_SIZE, pValue->m_pImage->m_size, &pValue->m_pImage->m_size, IDS_STRING_WIDTH, IDS_STRING_HEIGHT); pItem->SetReadOnly(TRUE); } //网格数目 long numx = 0, numy = 0, numz = 0; CString smn; int dem = pValue->GetNumber(numx, numy, &numz); switch (dem) { case 2: case 0: smn.Format("%ld, %ld", numx, numy); break; case 3: smn.Format("%ld, %ld, %ld", numx, numy, numz); break; } pItem = ItemAdd.AddItemString(IDS_GI_MESH_MN, smn); pItem->SetReadOnly(TRUE); //维数 m_nDimensionSel = 0; if (dem == 3) m_nDimensionSel = 1; pItem = ItemAdd.AddItemCombo(IDS_STRING_GRID_DIMENSION, IDS_STRING_GRID_DIMENSION_MODE, m_nDimensionSel, &m_nDimensionSel); pItem->SetReadOnly(TRUE); pItem = grid.AddCategory(IDS_MESH_COLOR_RULER); ItemAdd.SetItem(pItem); pItem->Expand(); m_bRuler = pValue->IsDrawRuler(); ItemAdd.AddItemBool(IDS_GI_MESH_RULER, m_bRuler, &m_bRuler); //是否显示标尺 m_bUpdateRuler = pValue->IsUpdateRuler(); ItemAdd.AddItemBool(IDS_MESH_COLOR_RULER_UPDATE, m_bUpdateRuler, &m_bUpdateRuler); //是否更新标尺 m_bReversal = pValue->m_pRuler->IsReversal(); ItemAdd.AddItemBool(IDS_GI_MESH_REVERSAL, m_bReversal, &m_bReversal); //是否反转显示标尺 CColorRuler* pRuler = pValue->m_pRuler; m_RulerIdea = GetRulerIdea(pRuler->GetMode()); pItem = ItemAdd.AddItemCombo(IDS_GI_NET_VIEW_IDEA, IDS_MESH_COLOR_RULER_MODE, m_RulerIdea, &m_RulerIdea); //坐标 m_point.SetPoint(pRuler->x0, pRuler->y0); pItem = ItemAdd.AddItemPoint(IDS_GI_COORDINATE, m_point, &m_point); pItem->SetReadOnly(m_bUpdateRuler); //高宽 pItem = ItemAdd.AddItemSize8(IDS_STRING_SIZE, pRuler->m_size, NULL, IDS_STRING_WIDTH, IDS_STRING_HEIGHT); pItem->SetReadOnly(m_bUpdateRuler); pItem = ItemAdd.AddItemDouble(IDS_STRING_TEXT_HEIGHT, pRuler->TextHeight, strFormat, NULL); pItem->SetReadOnly(m_bUpdateRuler); pItem = ItemAdd.AddItemDouble(IDS_STRING_MAXIMAL, pRuler->zmax, strFormat, NULL); pItem->SetReadOnly(m_bUpdateRuler); pItem = ItemAdd.AddItemDouble(IDS_STRING_MINIMUM, pRuler->zmin, strFormat, NULL); pItem->SetReadOnly(m_bUpdateRuler); pItem = ItemAdd.AddItemDouble(IDS_GI_STEP, pRuler->delt, strFormat, NULL); //pItem->SetReadOnly(m_bUpdateRuler); pItem = ItemAdd.AddItemLong(IDS_TREE_GI_SAVE_DECIMAL_DIGITS, pRuler->DecimalFraction, NULL); //pItem->SetReadOnly(m_bUpdateRuler); pItem = ItemAdd.AddItemLong(IDS_GI_PROPORTION_NUMBER, pRuler->num, NULL); CItem::InitPropertyGrid(grid); return TRUE; } */ /*BOOL CItemMesh::OnGridItemChangeValueMesh(CXTPPropertyGridItem* pItem) { COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); CMesh* pValue = (CMesh*)pOne->GetValue(); BOOL bUpdate = FALSE; switch (pItem->GetID()) { case IDS_GI_MESH_FUNCTION: pValue->SetMeshFunction(this->GetFunctionMode(modeFun)); GetDoc()->BeginProgress(IDS_GI_MESH_FUNCTION); pValue->GetBitmap(); GetDoc()->EndProgress(); bUpdate = TRUE; break; case IDS_STRING_ZRANGE: if (pValue->GetMesh()) { pValue->SetM(m_zrange.cx, m_zrange.cy); GetDoc()->BeginProgress(IDS_STRING_ZRANGE); pValue->GetBitmap(); GetDoc()->EndProgress(); bUpdate = TRUE; } break; case IDS_STRING_FILE_NAME: if (pValue->AutoReadFile(name)) pValue->SetName(name); bUpdate = TRUE; break; case IDS_GI_COLOR: pValue->color = color; GetDoc()->BeginProgress(IDS_GI_COLOR); pValue->GetBitmap(); GetDoc()->EndProgress(); bUpdate = TRUE; break; case IDS_GI_MESH_TIMES: pValue->m_nTimes = ((CXTPPropertyGridItemNumber*)pItem)->GetNumber(); GetDoc()->BeginProgress(IDS_GI_MESH_TIMES); pValue->GetBitmap(); GetDoc()->EndProgress(); bUpdate = TRUE; break; case IDS_STRING_TRANSPARENT: switch (typeIndex) { case 0: pValue->SetTransparentMode(0); pValue->RemoveAlpha(); break; case 1: pValue->SetTransparentMode(IMAGE_TRANSPARENT_ALPHA); pValue->SetTransparentColor(m_levelAlpha); break; case 2: pValue->SetTransparentMode(IMAGE_TRANSPARENT_COLOR); pValue->SetTransparentColor(m_levelAlpha); break; } { CXTPPropertyGridItem* pFindItem = this->FindItem(pItem, ID_IMAGE_TRANSPARENT_COLOR); if (pFindItem) pFindItem->SetReadOnly(!pValue->IsTransparent()); } bUpdate = TRUE; break; case ID_IMAGE_TRANSPARENT_COLOR: if (pValue->GetTransparentMode() == IMAGE_TRANSPARENT_ALPHA) { if (m_levelAlpha > 255) m_levelAlpha = 255; } else if (pValue->GetTransparentMode() == IMAGE_TRANSPARENT_COLOR) { if (m_levelAlpha > RGB(255, 255, 255)) m_levelAlpha = RGB(255, 255, 255); } if (m_levelAlpha < 0) m_levelAlpha = 0; pValue->SetTransparentColor(m_levelAlpha); bUpdate = TRUE; break; case IDS_GI_COORDINATE: pValue->m_pRuler->x0 = m_point.x0; pValue->m_pRuler->y0 = m_point.y0; bUpdate = TRUE; break; case IDS_GI_MESH_RULER: pValue->EnableDrawRuler(m_bRuler); { CRect8 rt = pValue->GetRulerRange(); CRect rect = GetDC()->GetScreen(rt); rect.InflateRect(2, 2); GetDoc()->CDrawDoc::Invalidate(rect); } bUpdate = TRUE; break; case IDS_MESH_COLOR_RULER_UPDATE: pValue->EnableUpdateRuler(m_bUpdateRuler); pValue->UpdateColorRuler(); bUpdate = TRUE; break; case IDS_GI_MESH_REVERSAL: pValue->m_pRuler->EnableReversal(m_bReversal ? true : false); bUpdate = TRUE; break; case IDS_STRING_SIZE: pValue->m_pRuler->m_size = ((CCustomItemPoint*)pItem)->GetValuePoint(); bUpdate = TRUE; break; case IDS_GI_NET_VIEW_IDEA: { DWORD orm = pValue->m_pRuler->GetMode(); DWORD rm = GetRulerMode(m_RulerIdea); pValue->m_pRuler->SetMode(rm); if (((rm == COLOR_RULER_H_SMOOTH || rm == COLOR_RULER_H_GRID) && (orm == COLOR_RULER_V_SMOOTH || orm == COLOR_RULER_V_GRID)) || ((orm == COLOR_RULER_H_SMOOTH || orm == COLOR_RULER_H_GRID) && (rm == COLOR_RULER_V_SMOOTH || rm == COLOR_RULER_V_GRID))) AfxGetPublicFunction()->ExchangeXY(pValue->m_pRuler->m_size.cx, pValue->m_pRuler->m_size.cy); } bUpdate = TRUE; break; case IDS_STRING_TEXT_HEIGHT: pValue->m_pRuler->TextHeight = ((CXTPPropertyGridItemDouble*)pItem)->GetDouble(); bUpdate = TRUE; break; case IDS_STRING_MAXIMAL: pValue->m_pRuler->zmax = ((CXTPPropertyGridItemDouble*)pItem)->GetDouble(); bUpdate = TRUE; break; case IDS_STRING_MINIMUM: pValue->m_pRuler->zmin = ((CXTPPropertyGridItemDouble*)pItem)->GetDouble(); bUpdate = TRUE; break; case IDS_GI_STEP: pValue->m_pRuler->delt = ((CXTPPropertyGridItemDouble*)pItem)->GetDouble(); bUpdate = TRUE; break; case IDS_TREE_GI_SAVE_DECIMAL_DIGITS: pValue->m_pRuler->DecimalFraction = atol(pItem->GetValue());; bUpdate = TRUE; break; case IDS_GI_PROPORTION_NUMBER: pValue->m_pRuler->num = atol(pItem->GetValue());; bUpdate = TRUE; break; } return bUpdate | CItem::OnGridItemChangeValue(pItem); }*/ int CItemMesh::GetFunctionIdea(DWORD nFunMode) { switch (nFunMode) { case MESH_DIFFERENTIAL_X: return 1; case MESH_DIFFERENTIAL_Y: return 2; case MESH_DIFFERENTIAL_XY: return 3; case MESH_DIFFERENTIAL_X2: return 4; case MESH_DIFFERENTIAL_Y2: return 5; case MESH_DIFFERENTIAL_XY2: return 6; } return 0; } DWORD CItemMesh::GetFunctionMode(int nFunIdea) { switch (nFunIdea) { case 1: return MESH_DIFFERENTIAL_X; case 2: return MESH_DIFFERENTIAL_Y; case 3: return MESH_DIFFERENTIAL_XY; case 4: return MESH_DIFFERENTIAL_X2; case 5: return MESH_DIFFERENTIAL_Y2; case 6: return MESH_DIFFERENTIAL_XY2; } return 0; } int CItemMesh::GetRulerIdea(DWORD nMode) { switch (nMode) { case COLOR_RULER_H_SMOOTH: return 0; case COLOR_RULER_H_GRID: return 1; case COLOR_RULER_V_SMOOTH: return 2; case COLOR_RULER_V_GRID: return 3; } return 0; } DWORD CItemMesh::GetRulerMode(int nIdea) { switch (nIdea) { default: case 0: return COLOR_RULER_H_SMOOTH; case 1: return COLOR_RULER_H_GRID; case 2: return COLOR_RULER_V_SMOOTH; case 3: return COLOR_RULER_V_GRID; } return COLOR_RULER_H_SMOOTH; } void CItemMesh::SaveAs(COne* pOne, LPCTSTR filePath, int index) { if (pOne == NULL) return; CString name = filePath; if (index < 0) { name += _T(".keg"); index = 0; } CMesh* pMesh = (CMesh*)pOne->GetValue(); if (pMesh->GetMesh() == NULL || name == "") return; switch (index) { case 0://*.keg pMesh->WriteMesh(name, MESH_DFG); break; case 1://*.grd pMesh->WriteGrid_SurferAscii(name); break; case 2://*.grd pMesh->WriteGrid_SurferBinary6(name); break; case 3: pMesh->WriteGrid_GeoFrameAscii(name); break; default: case 4://*.jpg, *.tif case 5: { if (pMesh->NeedVectorDraw()) { //矢量 pMesh->m_imgCapture.Save(name, CXIMAGE_FORMAT_BMP); } else { if (pMesh->GetImage() != NULL) pMesh->GetImage()->SaveAs(name); else ::AfxMessageBox("ERROR: NULL Image Data"); } break; } } } void CItemMesh::SaveAsOnlyData(COne* pOne, LPCTSTR filePath) { if (pOne == NULL) return; CMesh* pMesh = (CMesh*)pOne->GetValue(); if (pMesh->GetMesh() == NULL) return; CFile fw; if (!fw.Open(filePath, CFile::modeCreate | CFile::modeWrite)) { ::AfxMessageBox("Open file to write error!"); return; } pMesh->WriteOnlyDataToXYZ(fw, pMesh->m_nTimes, CUR_VERSION); fw.Close(); } CItemMesh* _pItemMeshContour_Only = NULL; POSITION posCurrent = nullptr; POSITION AddContourCurve(CCurve *curve, CString strLayer) { if (curve == NULL)return NULL; if (_pItemMeshContour_Only == NULL) return NULL; CCurveEx *ce = new CCurveEx(curve->num); for (int i = 0; i < ce->num; i++) { ce->x[i] = curve->x[i]; ce->y[i] = curve->y[i]; ce->z[i] = curve->z[i]; } ce->nPoint = curve->nPoint; ce->GetLocation(); //POSITION pos = NULL; if (curve->name) ce->SetName(curve->name); //pos = _pItemMeshContour_Only->AddElement(ce, DOUBLEFOX_CURVE, true, false); posCurrent = _pItemMeshContour_Only->GetDoc()->GetDraw()->InsertElementAfter(posCurrent, ce, DOUBLEFOX_CURVE); _pItemMeshContour_Only->GetDoc()->GetDraw()->SetElementLayer(posCurrent, strLayer); _pItemMeshContour_Only->m_posAddList.AddTail(posCurrent); return posCurrent; } //平滑操作 bool CItemMesh::GridSmooth(COne* pOne, double coefficient, int smoothNumber) { if (pOne == NULL) return false; m_nSelect = MESH_GRID_SMOOTH; POSITION pos = GetDoc()->GetDraw()->Find(pOne); if (pos == NULL) return false; //POSITION bkpos = GetPos(); //SetPos(pos); //CPropertiesSheet sheet(IDS_STRING_MESH_SMOOTH, GetView(), 0, FALSE); //sheet.SetItem(this); //if (sheet.DoModal() != IDOK) //{ //(bkpos); //m_nSelect = 0; //return; //} //SetPos(bkpos); m_nSelect = MESH_DEFAULT; CMesh* pMesh = (CMesh*)pOne->GetValue(); if (pMesh == NULL) return false; CActionBackupItem *pAction = new CActionBackupItem(GetDoc(), IDS_STRING_MESH_SMOOTH); pAction->Backup(pOne); //GetDoc()->BeginProgress(IDS_STRING_MESH_SMOOTH); pMesh->Smooth(coefficient, smoothNumber); //GetDoc()->EndProgress(); //GetDoc()->Invalidate(pos); pAction->BackupNew(); GetDoc()->SetActionItem(pAction); return true; } wchar_t * CItemMesh::GetInformationForGeneratingContour() { POSITION pos = GetPos(); if (pos == nullptr) return nullptr; COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(pos); CMesh* pValue = (CMesh*)pOne->GetValue(); CString strFormat = GetFloatFormatString(); m_zrange.SetSize(0, 0); pValue->GetM(m_zrange.cx, m_zrange.cy); m_contourStep = (m_zrange.cy - m_zrange.cx) / 20; m_contourStep = AfxGetPublicFunction()->ContourStep(m_contourStep); m_contourMarkStep = 5; CString infoStr; infoStr.Format("%.8lf;%d;%.8lf;%.8lf;%s;%s", m_contourStep, m_contourMarkStep, m_zrange.cx, m_zrange.cy, m_strLayerMark, m_strLayerOther); return AsciiToUnicodeChar(infoStr.GetBuffer()); //pItem = grid.AddCategory(IDS_STRING_TOOLBAR_LAYER); //ItemAdd.SetItem(pItem); pItem->Expand(); //pItem = ItemAdd.AddItemString(IDS_STRING_MESH_CONTOUR_MARK_LAYER, m_strLayerMark, &m_strLayerMark); //pItem = ItemAdd.AddItemString(IDS_STRING_MESH_CONTOUR_OTHER_LAYER, m_strLayerOther, &m_strLayerOther); //if (pValue->GetMeshType() == MESH_TEXT || // pValue->GetMeshType() == MESH_DFG || // pValue->GetMeshType() == MESH_FXY) //{ //pItem = grid.AddCategory(IDS_STRING_FAULTAGE); //ItemAdd.SetItem(pItem); pItem->Expand(); //pItem = ItemAdd.AddItemCombo(IDS_STRING_FAULTAGE_MODE_SEL, IDS_STRING_FAULTAGE_MODE, m_nFaultageMode, &m_nFaultageMode); //ItemAdd.SetItem(pItem); pItem->Expand(); //CString strFilter = _T("DoubleFox Files (*.dfd)|*.dfd|All Files (*.*)|*.*||"); //pItem = ItemAdd.AddItemFileBox(TRUE, IDS_FAULTAGE_FILE, NULL, m_strFaultageFile, &m_strFaultageFile, strFilter, FALSE); //pItem->SetReadOnly(TRUE); //CString layer = GetGridItemComboLayer(); //pItem = ItemAdd.AddItemCombo(IDS_FAULTAGE_LAYER, layer, m_strFaultageLayer, &m_strFaultageLayer); //pItem->SetReadOnly(TRUE); //} } bool CItemMesh::CreateContour(COne* pOne, char * infoString) { if (pOne == NULL) return false; if (!ParseInformationOfCreatingContour(infoString)) return false; m_nSelect = MESH_CREATE_CONTOUR; POSITION pos = GetDoc()->GetDraw()->Find(pOne); if (pos == NULL) return false; //POSITION bkpos = GetPos(); //SetPos(pos); //CPropertiesSheet sheet(IDS_STRING_MESH, GetView(), 0, FALSE); //sheet.SetItem(this); //if (sheet.DoModal() != IDOK) //{ // SetPos(bkpos); // m_nSelect = 0; // return; //} //SetPos(bkpos); m_nSelect = MESH_DEFAULT; _pItemMeshContour_Only = this; m_posAddList.RemoveAll(); CMesh* pMesh = (CMesh*)pOne->GetValue(); if (m_strLayerMark.IsEmpty()) m_strLayerMark = _T("Layer:\\Contour\\Mark"); if (m_strLayerOther.IsEmpty()) m_strLayerOther = _T("Layer:\\Contour\\Other"); CString curLayerName = GetDoc()->GetDraw()->GetCurrentLayer()->GetPathName(); CLayer* pMarkLayer = GetDoc()->GetDraw()->FindLayer(m_strLayerMark); CLayer* pOtherLayer = GetDoc()->GetDraw()->FindLayer(m_strLayerOther); BOOL bAddMarkLayer = FALSE; BOOL bAddOtherLayer = FALSE; if (pMarkLayer == NULL) { bAddMarkLayer = TRUE; pMarkLayer = GetDoc()->GetDraw()->FindAddLayer(m_strLayerMark); pMarkLayer->HowToViewCurve = new CHowToViewCurve(); pMarkLayer->HowToViewCurve->EnableDrawSourceCurve(FALSE); CCurveInName* pInName = new CCurveInName(); CRect8 rect = pMesh->GetRect(); pInName->text_h = rect.Width() / 300; pInName->m_size.cx = pInName->text_h*0.06; pMarkLayer->HowToViewCurve->Add(pInName); } if (pOtherLayer == NULL) { bAddOtherLayer = TRUE; pOtherLayer = GetDoc()->GetDraw()->FindAddLayer(m_strLayerOther); pOtherLayer->HowToViewCurve = new CHowToViewCurve(); pOtherLayer->HowToViewCurve->EnableDrawSourceCurve(FALSE); CCurveProperties* pview = new CCurveProperties(); pview->color = RGB(0, 255, 0); pOtherLayer->HowToViewCurve->Add(pview); } //设置断层信息 CDimension3D* pDfg = (CDimension3D*)pMesh->GetMesh(); switch (m_nFaultageMode) { case 0://没有断层 break; case 1://断层在文件中 pDfg->CDimensionBase::EmptyLink();//清空已有的断层信息 switch (pMesh->GetMeshType()) { case MESH_TEXT: case MESH_DFG: case MESH_FXY: pDfg->Faultage(m_strFaultageFile); break; case MESH_FUN_2D: default: break; } break; case 2://断层在类别中 switch (pMesh->GetMeshType()) { case MESH_TEXT: case MESH_DFG: case MESH_FXY: pDfg->CDimensionBase::EmptyLink();//清空已有的断层信息 { CCurveEx* pCurve; COne* pOne; CPositionList select; if (GetDoc()->GetDraw()->GetElement(m_strFaultageLayer, select, FALSE) > 0) { POSITION pt; POSITION pos = select.GetHeadPosition(); while (pos) { pt = select.GetNext(pos); pOne = GetDoc()->GetDraw()->GetAt(pt); if (pOne->GetType() != DOUBLEFOX_CURVE) continue; pCurve = (CCurveEx*)pOne->GetValue(); pDfg->Faultage(*(CCurve*)pCurve); } } } break; case MESH_FUN_2D: default: break; } break; } //生成等值线 posCurrent = pos; pMesh->ContourCreate(AddContourCurve, m_contourStep, m_contourMarkStep, m_strLayerMark, m_strLayerOther, m_zrange.cx, m_zrange.cy); if (m_posAddList.GetCount() > 0) { CActionListItem* pAction = new CActionListItem(GetDoc(), ID_MESH_CREATE_CONTOUR); if (bAddMarkLayer) pAction->AddLayerAddItem(pMarkLayer, curLayerName); if (bAddOtherLayer) pAction->AddLayerAddItem(pOtherLayer, curLayerName); pAction->AddAddItem(m_posAddList); GetDoc()->SetActionItem(pAction); m_posAddList.RemoveAll(); } _pItemMeshContour_Only = NULL; return true; } //初始化网格平滑属性框 /*BOOL CItemMesh::InitPropertyGridSmooth(CXTPPropertyGrid& grid) { ASSERT(GetPos()); CPropertyGridItemAdd ItemAdd(NULL); CXTPPropertyGridItem* pItem = grid.AddCategory(IDS_STRING_MESH); ItemAdd.SetItem(pItem); pItem->Expand(); COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); CString strFormat = GetFloatFormatString(); m_smoothcoef = 1.0; m_smthtimes = 10; pItem = ItemAdd.AddItemDouble(IDS_STRING_MESH_SMOOTH_COEFFICIENT, m_smoothcoef, strFormat, &m_smoothcoef); pItem = ItemAdd.AddItemLong(IDS_STRING_MESH_SMOOTH_TIMES, m_smthtimes, &m_smthtimes); return TRUE; }*/ //BOOL CItemMesh::OnGridItemChangeValueForContour(CXTPPropertyGridItem* pItem) //{ // COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); // CMesh* pValue = (CMesh*)pOne->GetValue(); // CXTPPropertyGridItem* pFind; // BOOL bUpdate = FALSE; // switch (pItem->GetID()) // { // case IDS_STRING_FAULTAGE_MODE_SEL: // bUpdate = TRUE; // switch (m_nFaultageMode) // { // case 0: //没有断层 // pFind = FindItem(pItem, IDS_FAULTAGE_FILE); // if (pFind)pFind->SetReadOnly(TRUE); // pFind = FindItem(pItem, IDS_FAULTAGE_LAYER); // if (pFind)pFind->SetReadOnly(TRUE); // break; // case 1: //断层数据在文件中 // pFind = FindItem(pItem, IDS_FAULTAGE_FILE); // if (pFind)pFind->SetReadOnly(FALSE); // pFind = FindItem(pItem, IDS_FAULTAGE_LAYER); // if (pFind)pFind->SetReadOnly(TRUE); // break; // case 2: //断层数据在类别中 // pFind = FindItem(pItem, IDS_FAULTAGE_FILE); // if (pFind)pFind->SetReadOnly(TRUE); // pFind = FindItem(pItem, IDS_FAULTAGE_LAYER); // if (pFind)pFind->SetReadOnly(FALSE); // break; // } // break; // default: // break; // } // return bUpdate; //} void CItemMesh::OnDraw(CXyDC* pXyDC, CDC* pDC) { OnDraw(pXyDC); } void CItemMesh::OnDraw(CXyDC* pDC) { if (!IsEditState()) return; switch (m_nSelect) { case MESH_EDIT_NODE: DrawNode(pDC); break; case MESH_HISTOGRAM: DrawHistogram(pDC); break; } } void CItemMesh::EditNode(CSigmaView* pView, CDC *pDC, CRect rt) { pDrawerDC = pDC; //GetDC()->Create(pDC); m_nSelect = MESH_EDIT_NODE; clientRect = rt; } void CItemMesh::DrawNode(CXyDC* pDC, CRect rt) { CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); //CRect rt; ////rt = GetView()->GetClientRect(); //CSigmaView* pView = GetView(); //rt = pView->m_client; long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); long sx = 3; int od = pDC->GetDC()->SetROP2(R2_NOTXORPEN); CPen* pb = (CPen*)pDC->GetDC()->SelectStockObject(BLACK_PEN); CPoint pt; int dx = (int)(pDC->GetRealWidth(sx * 2) / ddx) + 1; int dy = (int)fabs(pDC->GetRealHeight(sx * 2) / ddy) + 1; for (int i = 0; i < numx; i += dx) { for (int j = 0; j < numy; j += dy) { pt = pDC->GetScreen(pValue->x(i), pValue->y(j)); if (!rt.PtInRect(pt))continue; pDC->GetDC()->MoveTo(pt.x - sx + 1, pt.y); pDC->GetDC()->LineTo(pt.x + sx, pt.y); pDC->GetDC()->MoveTo(pt.x, pt.y - sx + 1); pDC->GetDC()->LineTo(pt.x, pt.y + sx); } } pDC->GetDC()->SetROP2(od); pDC->GetDC()->SelectObject(pb); if (m_bDrawPrevPoint) DrawFocus(m_ptPrevPoint); } void CItemMesh::DrawNode(CXyDC* pDC) { CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); CRect rt; //rt = GetView()->GetClientRect(); CSigmaView* pView = GetView(); //rt = pView->m_client; rt = clientRect; long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); long sx = 3; int od = pDC->GetDC()->SetROP2(R2_NOTXORPEN); CPen* pb = (CPen*)pDC->GetDC()->SelectStockObject(BLACK_PEN); CPoint pt; int dx = (int)(pDC->GetRealWidth(sx * 2) / ddx) + 1; int dy = (int)fabs(pDC->GetRealHeight(sx * 2) / ddy) + 1; for (int i = 0; i < numx; i += dx) { for (int j = 0; j < numy; j += dy) { pt = pDC->GetScreen(pValue->x(i), pValue->y(j)); if (!rt.PtInRect(pt))continue; pDC->GetDC()->MoveTo(pt.x - sx + 1, pt.y); pDC->GetDC()->LineTo(pt.x + sx, pt.y); pDC->GetDC()->MoveTo(pt.x, pt.y - sx + 1); pDC->GetDC()->LineTo(pt.x, pt.y + sx); } } pDC->GetDC()->SetROP2(od); pDC->GetDC()->SelectObject(pb); if (m_bDrawPrevPoint) DrawFocus(m_ptPrevPoint); } void CItemMesh::DrawFocus(CPoint2D point) { int od = GetDC()->GetDC()->SetROP2(R2_NOTXORPEN); CPen* pb = (CPen*)GetDC()->GetDC()->SelectStockObject(BLACK_PEN); long sx = 3; double dx = GetDC()->GetRealWidth(sx * 2); double dy = GetDC()->GetRealHeight(sx * 2); CCurveEx cu(5); cu.x[0] = point.x0 - dx; cu.y[0] = point.y0; cu.x[1] = point.x0; cu.y[1] = point.y0 - dy; cu.x[2] = point.x0 + dx; cu.y[2] = point.y0; cu.x[3] = point.x0; cu.y[3] = point.y0 + dy; cu.x[4] = point.x0 - dx; cu.y[4] = point.y0; cu.GetLocation(); cu.m_type = PLINE_SOLID; GetDC()->Draw(cu, RGB(255, 0, 0)); //GetDC()->Draw(cu, RGB(0, 255, 0)); GetDC()->GetDC()->SetROP2(od); GetDC()->GetDC()->SelectObject(pb); } int CItemMesh::OnMouseMove(CDC *pDC, UINT nFlags, CPoint point) { if (m_nSelect == MESH_EDIT_NODE) { if (!IsEditState()) return 1; CPoint2D dp = GetDC()->GetReal(point); CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); double x0, y0; pValue->GetOrg(x0, y0); long i = AfxGetPublicFunction()->FloatToLong((dp.x0 - x0) / ddx); long j = AfxGetPublicFunction()->FloatToLong((dp.y0 - y0) / ddy); if (m_bDrawPrevPoint) { //DrawFocus(m_ptPrevPoint); m_bDrawPrevPoint = FALSE; } if (i < 0 || i >= numx || j < 0 || j >= numy) return 1; m_ptPrevPoint.x0 = pValue->x(i); m_ptPrevPoint.y0 = pValue->y(j); m_bDrawPrevPoint = TRUE; GetDC()->Create(pDC); DrawFocus(m_ptPrevPoint); TRACE("draw pt.x=%f,pt.y=%f\n", m_ptPrevPoint.x0, m_ptPrevPoint.y0); } return 1; } bool CItemMesh::FindNodeLocation(CDC *pDC, CPoint point, int& locationX, int& locationY) { if (m_nSelect == MESH_EDIT_NODE) { if (!IsEditState()) return false; GetDC()->Create(pDC); CPoint2D dp = GetDC()->GetReal(point); CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); double x0, y0; pValue->GetOrg(x0, y0); long i = AfxGetPublicFunction()->FloatToLong((dp.x0 - x0) / ddx); long j = AfxGetPublicFunction()->FloatToLong((dp.y0 - y0) / ddy); if (i < 0 || i >= numx || j < 0 || j >= numy) { return false; } CPoint ptSc = GetDC()->GetScreen(pValue->x(i), pValue->y(j)); locationX = ptSc.x; locationY = ptSc.y; //TRACE("draw locationX=%f,locationY=%f\n", locationX, locationY); return true; } else { return false; } } CMesh* CItemMesh::GetMesh(void) { if (GetPos() == NULL) return NULL; /*COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); if (pOne->GetType() != DOUBLEFOX_MESH) return NULL; return (CMesh*)pOne->GetValue();*/ return NULL; } bool CItemMesh::GridPointNoExist(UINT nFlags, CPoint point) { if (m_nSelect == MESH_EDIT_NODE) { if (!IsEditState()) return false; CPoint2D dp = GetDC()->GetReal(point); COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); CMesh* pValue = (CMesh*)pOne->GetValue(); long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); double x0, y0; pValue->GetOrg(x0, y0); long i = AfxGetPublicFunction()->FloatToLong((dp.x0 - x0) / ddx); long j = AfxGetPublicFunction()->FloatToLong((dp.y0 - y0) / ddy); if (i < 0 || i >= numx) return false; if (j < 0 || j >= numy) return false; return true; } return false; } CString CItemMesh::GetGridValue(UINT nFlags, CPoint point) { if (m_nSelect == MESH_EDIT_NODE) { if (!IsEditState()) return ""; CPoint2D dp = GetDC()->GetReal(point); COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); CMesh* pValue = (CMesh*)pOne->GetValue(); long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); double x0, y0; pValue->GetOrg(x0, y0); long i = AfxGetPublicFunction()->FloatToLong((dp.x0 - x0) / ddx); long j = AfxGetPublicFunction()->FloatToLong((dp.y0 - y0) / ddy); CString cStrX, cStrY, cStrZ, cStrRow, cStrCol, zMin, zMax, rtnValue; double zmin, zmax; pValue->GetM(zmin, zmax); cStrX.Format(_T("%lf"), pValue->x(i)); cStrY.Format(_T("%lf"), pValue->y(j)); cStrZ.Format(_T("%lf"), pValue->GetValue(i, j)); cStrRow.Format("%ud ", i); cStrCol.Format("%ud ", j); zMin.Format(_T("%lf"), zmin); zMax.Format(_T("%lf"), zmax); rtnValue = cStrX + "," + cStrY + "," + cStrZ + "," + cStrRow + "," + cStrCol + "," + zMin + "," + zMax; return rtnValue; } return _T(""); } void CItemMesh::ConfirmGridBtn() { } void CItemMesh::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point, int vk) { if (m_nSelect == MESH_EDIT_NODE) { if (!IsEditState()) return; CPoint2D dp = GetDC()->GetReal(point); COne* pOne = (COne*)GetDoc()->GetDraw()->GetAt(GetPos()); CMesh* pValue = (CMesh*)pOne->GetValue(); long numx, numy; pValue->GetNumber(numx, numy); double ddx, ddy; pValue->GetDelt(ddx, ddy); double x0, y0; pValue->GetOrg(x0, y0); long i = AfxGetPublicFunction()->FloatToLong((dp.x0 - x0) / ddx); long j = AfxGetPublicFunction()->FloatToLong((dp.y0 - y0) / ddy); if (i < 0 || i >= numx) return; if (j < 0 || j >= numy) return; //CDlgGridNodeEdit dlg; //double ov = pValue->GetValue(i, j); //dlg.x = pValue->x(i); //dlg.y = pValue->y(j); //dlg.z = ov; //dlg.m_row = i; //dlg.m_col = j; //pValue->GetM(dlg.zmin, dlg.zmax); //if (dlg.DoModal() != IDOK) return; //double nv = dlg.z; //pValue->SetZ(i, j, nv); //CRect8 rt; //rt.SetRect(pValue->x(i - 1), pValue->y(j - 1), pValue->x(i + 2), pValue->y(j + 2)); //CRect rect = GetDC()->GetScreen(rt); //GetDoc()->CDrawDoc::Invalidate(&rect); //GetDoc()->SetModifiedFlag(); //m_bDrawPrevPoint = FALSE; ////for undo/redo //point.x = i; //point.y = j; //GetDoc()->SetActionItem(new CActionGridNodeEditItem(GetDoc(), ID_MESH_EDIT_NODE, pOne, point, ov, nv)); } } int CItemMesh::GetEditMode(void) { return m_nSelect; } bool NItem::CItemMesh::GridNormalization(COne* pOne) { if (pOne == NULL) return false; CMesh* pMesh = (CMesh*)pOne->GetValue(); if (pMesh == NULL) return false; CActionBackupItem* pAction = new CActionBackupItem(GetDoc(), ID_MESH_EDIT_NODE); pAction->Backup(pOne); //处理归一化 (Z - Zmin)/(Zmax - Zmin) double zmax = pMesh->GetDfg()->zmax(); double zmin = pMesh->GetDfg()->zmin(); pMesh->GetM(zmin, zmax); double z; double invRange = 1.0 / (zmax - zmin); long numx, numy; pMesh->GetNumber(numx, numy); #pragma omp parallel for collapse(2) for (int i = 0; i < numx; i++) { for (int j = 0; j < numy; j++) { double z = pMesh->GetValue(i, j); pMesh->SetZ(i, j, (z - zmin) * invRange); } } pMesh->SetM(0 , 1); // 设置颜色 double dZMinOld = 0; double dZMaxOld = 0; pMesh->color.GetZRange(dZMinOld, dZMaxOld); CArray ColorList; int nColorCount = pMesh->color.GetCount(); for (int i = 0; i < nColorCount; i++) { CColorItem colorMesh = pMesh->color.GetColorItem(i); colorMesh.z = 0 + ((1 - 0) * (colorMesh.z - dZMinOld) / (dZMaxOld - dZMinOld)); ColorList.Add(colorMesh); } pMesh->color.SetZRange(0, 1); pMesh->color.SetColor(ColorList); pMesh->UpdateColorRuler(); pMesh->GetBitmap(); pAction->BackupNew(); GetDoc()->SetActionItem(pAction); return true; } bool NItem::CItemMesh::GridGenerationBoundary(COne* pOne) { if (!pOne) return false; CMesh* pMesh = (CMesh*)pOne->GetValue(); if (!pMesh) return false; long numx, numy; pMesh->GetNumber(numx, numy); if (numx <= 0 || numy <= 0) return false; CRect8 rect1 = pMesh->GetRect(); double xmin = rect1.left; double ymin = rect1.bottom; // 网格步长 double dx = 0, dy = 0; pMesh->GetDelt(dx, dy); // 假设 xmin, ymin 是第一个点的中心,边界计算需要偏移 // 如果 xmin 是网格边缘,则不需要偏移。通常Surfer网格xmin是中心。 // 为了和Python保持一致(cx - half_dx),我们假设网格点是中心。 double half_dx = dx * 0.5; double half_dy = dy * 0.5; // Z 值范围 double zLimitMin, zLimitMax; pMesh->GetM(zLimitMin, zLimitMax); CLayer* pLayer = GetDoc()->GetDraw()->FindAddLayer("边界"); auto IsValidCell = [&](int cx, int cy) -> bool { if (cx < 0 || cx >= numx || cy < 0 || cy >= numy) return false; double val = pMesh->GetValue(cx, cy); if (val <= -1e10) return false; return (val >= zLimitMin && val <= zLimitMax); }; struct Segment { Pnt p1, p2; bool used = false; }; std::vector segments; // 遍历所有格子,检查其 右边 和 上边 是否是边界 for (int j = 0; j < numy; ++j) { for (int i = 0; i < numx; ++i) { bool curr = IsValidCell(i, j); // 检查左边 (只在 i=0 时检查,或者是当前有效、左边无效) // 为了简化,我们遍历每个格子的四条边,如果是(有效|无效)分界线,就加入 if (!curr) continue; // 只处理有效格子,找它的轮廓边 // 4个邻居 int nx[4] = { i - 1, i + 1, i, i }; int ny[4] = { j, j, j - 1, j + 1 }; // 对应格子的4个角点 (左下, 右下, 左上, 右上) double xL = xmin + i * dx - half_dx; double xR = xmin + i * dx + half_dx; double yB = ymin + j * dy - half_dy; double yT = ymin + j * dy + half_dy; // 左边 if (!IsValidCell(i - 1, j)) segments.push_back({ {xL, yT}, {xL, yB} }); // 向下 // 右边 if (!IsValidCell(i + 1, j)) segments.push_back({ {xR, yB}, {xR, yT} }); // 向上 // 下边 if (!IsValidCell(i, j - 1)) segments.push_back({ {xL, yB}, {xR, yB} }); // 向右 // 上边 if (!IsValidCell(i, j + 1)) segments.push_back({ {xR, yT}, {xL, yT} }); // 向左 } } if (segments.empty()) return false; while (true) { std::vector loop; // 找一个未使用的起始线段 int startIdx = -1; for (int i = 0; i < segments.size(); ++i) { if (!segments[i].used) { startIdx = i; break; } } if (startIdx == -1) break; // 全部处理完 // 开始追踪 int currIdx = startIdx; while (currIdx != -1) { segments[currIdx].used = true; loop.push_back(segments[currIdx].p1); Pnt target = segments[currIdx].p2; int nextIdx = -1; // 在未使用的线段中找起点 == target 的 // 优化:网格数量大时这里会慢,但对于几千个点还可以接受 // 如果很慢,需要建立 spatial hash 或 map for (int i = 0; i < segments.size(); ++i) { if (!segments[i].used) { // 使用容差比较 if (std::abs(segments[i].p1.x - target.x) < 1e-5 && std::abs(segments[i].p1.y - target.y) < 1e-5) { nextIdx = i; break; } } } currIdx = nextIdx; // 如果找不到,说明闭合或断裂 } if (loop.size() < 4) continue; // 忽略太小的噪点 // Chaikin 平滑 (迭代2次,消除直角) std::vector smoothed = NoGeosUtils::ChaikinSmooth(loop, 2); // Douglas-Peucker 抽稀 double diag = std::sqrt(dx * dx + dy * dy); std::vector simplified; NoGeosUtils::DouglasPeucker(smoothed, diag * 1.0, simplified); if (simplified.size() < 3) continue; CCurveEx* ce = new CCurveEx(simplified.size()); for (int k = 0; k < (int)simplified.size(); k++) { ce->x[k] = simplified[k].x; ce->y[k] = simplified[k].y; } ce->GetLocation(); ce->EnableClose(true); // 闭合 COne* pOneNew = new COne(); pOneNew->SetValue(ce, DOUBLEFOX_CURVE); pOneNew->SetLayer(pLayer); GetDoc()->GetDraw()->AddTailOne(pOneNew); //元素增加操作 int nInfoID = ID_CUT_OUT_MAP_RECTANGLE; auto pAction = std::make_unique(GetDoc(), nInfoID); auto pActionAdd = std::make_unique(GetDoc(), IDS_STRING_ACTION_ADD, pOneNew); pAction->AddTailItem(pActionAdd.release()); GetDoc()->SetActionItem(pAction.release()); } return true; } bool NItem::CItemMesh::RBFGridExpansion( COne* pOne, int dx_left, int dx_right, int dy_top, int dy_bottom, int maskRadius, double smoothing, int neighbors, int type, int numStep) { CMesh* pMeshInit = (CMesh*)pOne->GetValue(); if (!pMeshInit) return false; CActionBackupItem* pAction = new CActionBackupItem(GetDoc(), ID_MESH_EDIT_NODE); pAction->Backup(pOne); int rem_l = dx_left; int rem_r = dx_right; int rem_t = dy_top; int rem_b = dy_bottom; const int STEP_LIMIT = (numStep <= 0) ? std::numeric_limits::max() : numStep; CArray ColorList; for (int i = 0; i < pMeshInit->color.GetCount(); ++i) { ColorList.Add(pMeshInit->color.GetColorItem(i)); } // 分步循环外扩 while (rem_l > 0 || rem_r > 0 || rem_t > 0 || rem_b > 0) { // 计算当前步长 int cur_l = (rem_l > STEP_LIMIT) ? STEP_LIMIT : rem_l; int cur_r = (rem_r > STEP_LIMIT) ? STEP_LIMIT : rem_r; int cur_t = (rem_t > STEP_LIMIT) ? STEP_LIMIT : rem_t; int cur_b = (rem_b > STEP_LIMIT) ? STEP_LIMIT : rem_b; // 获取当前状态的 Mesh (每一轮都是上一轮更新后的结果) CMesh* pMeshCurrent = (CMesh*)pOne->GetValue(); if (!pMeshCurrent) break; ExpContext ctx; CDimension2D* pDfgNew = nullptr; std::vector baseMask; std::vector validPoints; // PrepareGrid 会将上一轮的边缘数据作为 validPoints 返回 if (!PrepareGrid(pOne, cur_l, cur_r, cur_t, cur_b, ctx, pDfgNew, baseMask, validPoints)) { break; } // 收集需要插值的目标点 std::vector xq, yq; std::vector tIdx; CollectTargets(ctx, maskRadius, baseMask, xq, yq, tIdx); // 执行 RBF 核心算法 if (!validPoints.empty() && !xq.empty()) { try { // 构建 RBF 插值器 (KDTree 构建) NItem::RBFInterpolatorCpp interp(validPoints); // 配置参数 NItem::RbfParams params; switch (type) { case 0: params.kernel = NItem::K_LINEAR; break; case 1: params.kernel = NItem::K_MULTIQUIDRIC; break; case 2: params.kernel = NItem::K_INV_MULTIQUADRIC; break; case 3: params.kernel = NItem::K_GAUSSIAN; break; default: params.kernel = NItem::K_LINEAR; break; } params.epsilon = 0.0; params.smoothing = smoothing; params.neighbors = neighbors; params.auto_epsilon = true; // max_dist 计算 (关联 maskRadius) if (maskRadius > 0) { double avg_step = (ctx.dX + ctx.dY) / 2.0; // RBF 通常需要比 IDW 更大的搜索范围来构建矩阵,稍微放宽一点 params.max_dist = maskRadius * avg_step * 3.0; } else { params.max_dist = -1.0; } // 执行预测 int chunk = 40000; std::vector preds = interp.predict(xq, yq, params, -1, chunk); // 回填数据 for (size_t k = 0; k < preds.size(); ++k) { double v = preds[k]; int idx = tIdx[k]; int nx = idx % ctx.newNx; int ny = idx / ctx.newNx; if (!std::isnan(v) && v < 1.0e30) { // Clamping if (v > ctx.zmax) v = ctx.zmax; if (v < ctx.zmin) v = ctx.zmin; pDfgNew->SetValue(nx, ny, v); } else { double nearv = interp.get_nearest_value(xq[k], yq[k]); if (!std::isnan(nearv) && nearv < 1.0e30) pDfgNew->SetValue(nx, ny, nearv); } } } catch (...) {} } CMesh* pMeshNew = new CMesh(); pMeshNew->SetMesh(pDfgNew, MESH_DFG, FALSE); pMeshNew->color.SetZRange(ctx.zmin, ctx.zmax); pMeshNew->color.SetColor(ColorList); pMeshNew->UpdateColorRuler(); pMeshNew->GetBitmap(); pOne->SetValue(pMeshNew, DOUBLEFOX_MESH); rem_l -= cur_l; rem_r -= cur_r; rem_t -= cur_t; rem_b -= cur_b; } pAction->BackupNew(); GetDoc()->SetActionItem(pAction); return true; } bool NItem::CItemMesh::IDWGridExpansion( COne* pOne, int dx_left, int dx_right, int dy_top, int dy_bottom, int maskRadius, int k, int p, int numStep) { CMesh* pMeshInit = (CMesh*)pOne->GetValue(); if (!pMeshInit) return false; CActionBackupItem* pAction = new CActionBackupItem(GetDoc(), ID_MESH_EDIT_NODE); pAction->Backup(pOne); int rem_l = dx_left; int rem_r = dx_right; int rem_t = dy_top; int rem_b = dy_bottom; const int STEP_LIMIT = (numStep <= 0) ? std::numeric_limits::max() : numStep; CArray ColorList; for (int i = 0; i < pMeshInit->color.GetCount(); ++i) { ColorList.Add(pMeshInit->color.GetColorItem(i)); } while (rem_l > 0 || rem_r > 0 || rem_t > 0 || rem_b > 0) { int cur_l = (rem_l > STEP_LIMIT) ? STEP_LIMIT : rem_l; int cur_r = (rem_r > STEP_LIMIT) ? STEP_LIMIT : rem_r; int cur_t = (rem_t > STEP_LIMIT) ? STEP_LIMIT : rem_t; int cur_b = (rem_b > STEP_LIMIT) ? STEP_LIMIT : rem_b; CMesh* pMeshCurrent = (CMesh*)pOne->GetValue(); if (!pMeshCurrent) break; ExpContext ctx; CDimension2D* pDfgNew = nullptr; std::vector baseMask; std::vector validPoints; if (!PrepareGrid(pOne, cur_l, cur_r, cur_t, cur_b, ctx, pDfgNew, baseMask, validPoints)) { break; } std::vector xq, yq; std::vector tIdx; CollectTargets(ctx, maskRadius, baseMask, xq, yq, tIdx); // IDW 核心计算 if (!validPoints.empty() && !xq.empty()) { NItem::PointCloudAdaptor adaptor(validPoints); NItem::MyKDTree kdtree(2, adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10)); kdtree.buildIndex(); double max_dist_sq = -1.0; if (maskRadius > 0) { double avg_step = (ctx.dX + ctx.dY) / 2.0; double md = maskRadius * avg_step * 3.0; max_dist_sq = md * md; } int actual_k = std::max(1, std::min(k, (int)validPoints.size())); double power = (double)p; #pragma omp parallel for for (int i = 0; i < (int)tIdx.size(); ++i) { int idx = tIdx[i]; int nx = idx % ctx.newNx; int ny = idx / ctx.newNx; double qx = xq[i]; double qy = yq[i]; std::vector indices(actual_k); std::vector dists_sq(actual_k); double query_pt[2] = { qx, qy }; kdtree.knnSearch(&query_pt[0], actual_k, &indices[0], &dists_sq[0]); double sum_w = 0.0; double sum_wz = 0.0; double final_val = 1.70141e38; bool exact = false; for (int j = 0; j < actual_k; ++j) { double d2 = dists_sq[j]; if (max_dist_sq > 0 && d2 > max_dist_sq) continue; double d = std::sqrt(d2); if (d < 1e-9) { final_val = validPoints[indices[j]].z; exact = true; break; } double w = 1.0 / std::pow(d, power); sum_w += w; sum_wz += w * validPoints[indices[j]].z; } if (!exact) { if (sum_w > 0.0) final_val = sum_wz / sum_w; else final_val = validPoints[indices[0]].z; } if (!std::isnan(final_val) && final_val < 1.0e30) { if (final_val > ctx.zmax) final_val = ctx.zmax; if (final_val < ctx.zmin) final_val = ctx.zmin; pDfgNew->SetValue(nx, ny, final_val); } else { double nearv = validPoints[indices[0]].z; if (!std::isnan(nearv) && nearv < 1.0e30) pDfgNew->SetValue(nx, ny, nearv); } } } CMesh* pMeshNew = new CMesh(); pMeshNew->SetMesh(pDfgNew, MESH_DFG, FALSE); pMeshNew->color.SetZRange(ctx.zmin, ctx.zmax); pMeshNew->color.SetColor(ColorList); pMeshNew->UpdateColorRuler(); pMeshNew->GetBitmap(); pOne->SetValue(pMeshNew, DOUBLEFOX_MESH); rem_l -= cur_l; rem_r -= cur_r; rem_t -= cur_t; rem_b -= cur_b; } pAction->BackupNew(); GetDoc()->SetActionItem(pAction); return true; } void CItemMesh::Histogram(void) { m_nSelect = MESH_HISTOGRAM; /* m_pHistogramDlg = new CDlgHistogram(GetView()); m_pHistogramDlg->m_pItemMesh = this; m_pHistogramDlg->Create(GetView());*/ } void CItemMesh::SetZValueOfNodeSelected(double v) { if (!m_bDrawRangeZ) { return; } CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); CRect rt = GetView()->GetClientRect(); long sx = 3; CPoint pt; double z; long numx, numy; pValue->GetNumber(numx, numy); for (int i = 0; i < numx; i++) { for (int j = 0; j < numy; j++) { z = pValue->GetValue(i, j); if (zm_zrange.cy) continue; pValue->SetZ(i, j, v); } } } bool CItemMesh::SetZOfGridPoint(double z, int row, int column) { COne* pOne = (COne*)m_pDoc->GetDraw()->GetAt(GetPos()); if (!pOne) { return false; } CMesh* pValue = (CMesh*)pOne->GetValue(); long numx, numy; pValue->GetNumber(numx, numy); if (row < 0 || row >= numx) return false; if (column < 0 || column >= numy) return false; pValue->SetZ(row, column, z); return true; } void CItemMesh::GetAreaAndValueForSelected(double minZ, double maxZ, double * areaOut, double * volumeOut) { CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); long sx = 3; CPoint pt; double dx = 0; double dy = 0; pValue->GetDelt(dx, dy); double cellOfArea = dx * dy; *areaOut = 0; *volumeOut = 0; double area = 0; double volume = 0; double z; long numx, numy; pValue->GetNumber(numx, numy); for (int i = 0; i < numx; i++) { for (int j = 0; j < numy; j++) { z = pValue->GetValue(i, j); if (zmaxZ) continue; area = cellOfArea + area; volume = volume + (z - minZ)*cellOfArea; } } *areaOut = area; *volumeOut = volume; } bool NItem::CItemMesh::PrepareGrid(COne* pOne, int dx_l, int dx_r, int dy_t, int dy_b, ExpContext& ctx, CDimension2D*& pDfgNew, std::vector& baseMask, std::vector& validPoints) { CMesh* pMeshOld = (CMesh*)pOne->GetValue(); if (!pMeshOld) return false; CDimension2D* pOld = pMeshOld->GetDfg(); if (!pOld) return false; if (dx_l == 0 && dx_r == 0 && dy_t == 0 && dy_b == 0) { return false; } // 填充 Context ctx.oldNx = pOld->xnum(); ctx.oldNy = pOld->ynum(); ctx.oldX0 = pOld->xmin(); ctx.oldY0 = pOld->ymin(); ctx.dX = pOld->dx(); ctx.dY = pOld->dy(); pMeshOld->color.GetZRange(ctx.zmin, ctx.zmax); // 计算新尺寸 ctx.newNx = ctx.oldNx + dx_l + dx_r; ctx.newNy = ctx.oldNy + dy_t + dy_b; if (ctx.newNx <= 0 || ctx.newNy <= 0) {return false; } ctx.newX0 = ctx.oldX0 - dx_l * ctx.dX; ctx.newY0 = ctx.oldY0 - dy_b * ctx.dY; // 创建网格 pDfgNew = new CDimension2D(); pDfgNew->Create(ctx.newNx, ctx.newNy, ctx.newX0, ctx.newY0, ctx.dX, ctx.dY); pDfgNew->range[0] = pOld->range[0]; pDfgNew->range[1] = pOld->range[1]; const double INVALID_VAL = 1.70141e38; #pragma omp parallel for for (int i = 0; i < ctx.newNx * ctx.newNy; ++i) { pDfgNew->SetValue(i % ctx.newNx, i / ctx.newNx, INVALID_VAL); } // 拷贝数据 baseMask.assign(ctx.newNx * ctx.newNy, 0); validPoints.reserve(ctx.oldNx * ctx.oldNy); auto IsValid = [&](double v) { return !std::isnan(v) && v >= ctx.zmin && v <= ctx.zmax; }; for (int oy = 0; oy < ctx.oldNy; ++oy) { for (int ox = 0; ox < ctx.oldNx; ++ox) { double z = pOld->Value(ox, oy); if (IsValid(z)) { int nx = ox + dx_l; int ny = oy + dy_b; pDfgNew->SetValue(nx, ny, z); baseMask[ny * ctx.newNx + nx] = 1; validPoints.push_back({ ctx.oldX0 + ox * ctx.dX, ctx.oldY0 + oy * ctx.dY, z }); } } } return true; } void NItem::CItemMesh::CollectTargets(const ExpContext& ctx, int maskRadius, const std::vector& baseMask, std::vector& xq, std::vector& yq, std::vector& tIdx) { std::vector allowedMask; ComputeDilatedMask(ctx.newNx, ctx.newNy, maskRadius, baseMask, allowedMask); size_t est = (size_t)(ctx.newNx * ctx.newNy * 0.1); xq.reserve(est); yq.reserve(est); tIdx.reserve(est); for (int iy = 0; iy < ctx.newNy; ++iy) { for (int ix = 0; ix < ctx.newNx; ++ix) { int idx = iy * ctx.newNx + ix; // 逻辑:在膨胀范围内 且 原本无值 if (allowedMask[idx] == 1 && baseMask[idx] == 0) { xq.push_back(ctx.newX0 + ix * ctx.dX); yq.push_back(ctx.newY0 + iy * ctx.dY); tIdx.push_back(idx); } } } } void NItem::CItemMesh::Dilate1D_Line(const std::vector& in, std::vector& out, int width, int height, int radius, bool is_horizontal) { int outer_loop = is_horizontal ? height : width; int inner_loop = is_horizontal ? width : height; #pragma omp parallel for for (int i = 0; i < outer_loop; ++i) { for (int j = 0; j < inner_loop; ++j) { int idx = is_horizontal ? (i * width + j) : (j * width + i); if (in[idx] != 0) { // 如果当前点有值 int start = std::max(0, j - radius); int end = std::min(inner_loop - 1, j + radius); for (int k = start; k <= end; ++k) { int target_idx = is_horizontal ? (i * width + k) : (k * width + i); out[target_idx] = 1; } } } } } void NItem::CItemMesh::ComputeDilatedMask(int nx, int ny, int radius, const std::vector& input, std::vector& output) { if (radius <= 0) { output = input; // 半径<=0时不外扩 return; } // 临时 buffer std::vector temp(nx * ny, 0); output.assign(nx * ny, 0); // X轴膨胀 -> Y轴膨胀 (等同于方形核) Dilate1D_Line(input, temp, nx, ny, radius, true); Dilate1D_Line(temp, output, nx, ny, radius, false); } void CItemMesh::DrawHistogram(CXyDC* pDC) { if (!m_bDrawRangeZ) return; CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); CRect rt = GetView()->GetClientRect(); long sx = 3; int od = pDC->GetDC()->SetROP2(R2_NOTXORPEN); CPen* pb = (CPen*)pDC->GetDC()->SelectStockObject(BLACK_PEN); CPoint pt; double z; long numx, numy; pValue->GetNumber(numx, numy); for (int i = 0; i < numx; i++) { for (int j = 0; j < numy; j++) { z = pValue->GetValue(i, j); if (zm_zrange.cy) continue; pt = pDC->GetScreen(pValue->x(i), pValue->y(j)); if (!rt.PtInRect(pt)) continue; pDC->GetDC()->MoveTo(pt.x - sx + 1, pt.y); pDC->GetDC()->LineTo(pt.x + sx, pt.y); pDC->GetDC()->MoveTo(pt.x, pt.y - sx + 1); pDC->GetDC()->LineTo(pt.x, pt.y + sx); } } pDC->GetDC()->SetROP2(od); pDC->GetDC()->SelectObject(pb); } bool CItemMesh::ParseInformationOfCreatingContour(char * infoStr) { if (infoStr == 0) return false; std::string infoString(infoStr); std::vector tokens; Kit_StringTool_Split(infoString, tokens, ";"); if (tokens.size() != 9) return false; try { m_contourStep = std::stod(tokens[0]); m_contourMarkStep = std::stol(tokens[1]); m_zrange.cx = std::stod(tokens[2]); m_zrange.cy = std::stod(tokens[3]); m_strLayerMark = tokens[4].c_str(); m_strLayerOther = tokens[5].c_str(); m_nFaultageMode = std::stoi(tokens[6]); m_strFaultageFile = tokens[7].c_str(); m_strFaultageLayer = tokens[8].c_str(); } catch (std::exception ex) { std::cout << ex.what() << std::endl; } return true; } int CItemMesh::DeleteSelected(void) { if (!m_bDrawRangeZ) return 0; CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); //for redo/undo CPositionList select; select.AddTail(GetPos()); CActionBackupItem* pItem = new CActionBackupItem(GetDoc(), ID_MESH_HISTOGRAM, select); double zmin, zmax; pValue->GetM(zmin, zmax); zmin = (zmax - zmin) * 2; int count = pValue->DeleteValue(m_zrange.cx, m_zrange.cy, zmin); if (count > 0) { pValue->GetBitmap(); pItem->BackupNew(); GetDoc()->SetActionItem(pItem); } else delete pItem; return count; } void CItemMesh::SetHistogramRange(double zmin, double zmax) { m_bDrawRangeZ = TRUE; if (fabs(zmax - zmin) < 1e-10) m_bDrawRangeZ = FALSE; m_zrange.cx = zmin; m_zrange.cy = zmax; //GetDoc()->Invalidate(GetPos()); } /*void CItemMesh::OnInplaceButtonDown(CXTPPropertyGridItem* pItem) { if (pItem->GetID() != IDS_STRING_ZRANGE) return; int bakSelected = m_nSelect; m_nSelect = MESH_GET_RANGE; CPropertiesSheet sheet(IDS_STRING_ZRANGE, GetView(), 0, FALSE); sheet.SetItem(this); INT_PTR rt = sheet.DoModal(); m_nSelect = bakSelected; if (rt == IDOK) { CMesh* pValue = (CMesh*)GetDoc()->GetDraw()->GetAtValue(GetPos()); double zmin, zmax; pValue->GetM(zmin, zmax, TRUE, m_szInvalidateValueZ.cx, m_szInvalidateValueZ.cy); SetHistogramRange(zmin, zmax); if (m_bResetZ) { pValue->color.CreateZAverage(zmin, zmax); GetDoc()->BeginProgress(IDS_STRING_ZRANGE); pValue->GetBitmap(); GetDoc()->EndProgress(); } } }*/ static void Kit_StringTool_Split(const std::string & s, std::vector & tokens, const std::string & delimiters) { if (delimiters.size() == 0) { tokens.push_back(s); return; } //在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index开始。如果没找到就返回string::nops std::string::size_type lastPos = s.find_first_not_of(delimiters, 0); std::string::size_type pos = s.find_first_of(delimiters, lastPos); while (std::string::npos != pos || std::string::npos != lastPos) { tokens.push_back(s.substr(lastPos, pos - lastPos)); lastPos = s.find_first_not_of(delimiters, pos); pos = s.find_first_of(delimiters, lastPos); } }