#include "StdAfx.h" #include "SigmaView.h" #include "itemmesh.h" #include "ItemSelect.h" #include "ActionAddItem.h" #include "ActionModifiedMeshItem.h" struct StatisticsGraph { CHistogramStat * pStat; CMesh * pMesh; CItemMesh * pItemMesh; CRect graphOutRect; }; // 定义与 C# 传参对齐的结构体 struct ColorScaleEntry { double z; // 对应的网格数值 int r; int g; int b; int a; int isContinue; // 是否为连续色标 (m_bContinue) // 显式补齐 4 个字节,使总大小严格等于 32 字节 int _padding; }; wchar_t * AsciiToUnicodeChar(const char * str); char* UnicodeToAscii(const wchar_t * str); static void InitStatisticsGraph(StatisticsGraph * statisticsGraph); static CItemMesh * GetItemMesh(CSigmaView * pView) { if (pView == NULL) return 0; CItem * pItem = pView->GetItem(); if (pItem == NULL) return NULL; CItemMesh * itemMesh = dynamic_cast(pItem); return itemMesh; } extern "C" __declspec(dllexport) bool SurfaceGetInfo(CSigmaView* pView, POSITION elementPtr , int& numX, int& numY , double& dLocationX, double& dLocationY , double& dDeltX, double& dDeltY , double& maxX, double& maxY) { COne * pOne = pView->m_pDoc->GetDraw()->GetAt(elementPtr); if (pOne == 0) return false; CMesh* pValue = (CMesh*)pOne->GetValue(); CGrid* pGrid = pValue->GetMesh(); numX = pGrid->xnum(); numY = pGrid->ynum(); dLocationX = pGrid->xmin(); dLocationY = pGrid->ymin(); dDeltX = pGrid->dx(); dDeltY = pGrid->dy(); maxX = pGrid->xmax(); maxY = pGrid->ymax(); return true; } extern "C" __declspec(dllexport) bool SurfaceGetImageInfo(CSigmaView* pView, POSITION elementPtr , int& numX, int& numY , double& dLocationX, double& dLocationY , double& dDeltX, double& dDeltY , double& maxX, double& maxY) { COne * pOne = pView->m_pDoc->GetDraw()->GetAt(elementPtr); if (pOne == 0) return false; CImageInsert* pValue = (CImageInsert*)pOne->GetValue(); CRect8 range(1e100, -1e100, -1e100, 1e100); pValue->GetRange(range); numX = pValue->m_pImage->GetWidth(); numY = pValue->m_pImage->GetHeight(); dLocationX = range.left; dLocationY = range.bottom; dDeltX = 0; dDeltY = 0; maxX = range.right; maxY = range.top; return true; } extern "C" __declspec(dllexport) bool SurfaceGetInfoDefault(CSigmaView* pView , int& numX, int& numY , double& dLocationX, double& dLocationY , double& dDeltX, double& dDeltY , double& maxX, double& maxY) { CPositionList lstMesh; int nCount = pView->m_pDoc->m_pXy->GetElement(DOUBLEFOX_MESH, lstMesh, TRUE); if (nCount < 1 || lstMesh.IsEmpty()) { return false; } POSITION posMesh = nullptr; posMesh = lstMesh.GetHeadPosition(); if (posMesh == nullptr) { return false; } POSITION pt = lstMesh.GetNext(posMesh); CMesh* pMesh = (CMesh*)(pView->m_pDoc->m_pXy->GetAtValue(pt)); return SurfaceGetInfo(pView, pt, numX, numY, dLocationX, dLocationY, dDeltX, dDeltY, maxX, maxY); } /* extern "C" __declspec(dllexport) void SurfaceSaveAs(CSigmaView* pView, LPCTSTR filePath,int index, POSITION elementPtr) { CItemMesh * itemMesh = GetItemMesh(pView, elementPtr); if (itemMesh == NULL) return; COne* pOne = (COne*)(pView->m_pDoc->GetDraw()->GetAt(elementPtr)); itemMesh->SaveAs(pOne,filePath,index); } */ extern "C" __declspec(dllexport) void SurfaceSaveAs(CSigmaView* pView, LPCTSTR filePath, int index, POSITION elementPtr) { COne * pOne = pView->m_pDoc->GetDraw()->GetAt(elementPtr); if (pOne == 0) return ; CItemMesh itemMesh(pView->m_pDoc); itemMesh.SaveAs(pOne, filePath, index); } extern "C" __declspec(dllexport) void SaveDataPointOnly(CSigmaView* pView,LPCTSTR filePath, POSITION elementPtr) { COne * pOne = pView->m_pDoc->GetDraw()->GetAt(elementPtr); if (pOne == 0) return; CItemMesh itemMesh(pView->m_pDoc); itemMesh.SaveAsOnlyData(pOne, filePath); } extern "C" __declspec(dllexport) void CreateContour(CSigmaView* pView) { CItemMesh * itemMesh = new CItemMesh(pView->m_pDoc); COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); itemMesh->CreateContour(pOne, nullptr); } extern "C" __declspec(dllexport) int Sigma_GetInfoStringForCreatingContour(CSigmaView * pView, wchar_t ** infoStrAddress) { COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CMesh* pValue = (CMesh*)pOne->GetValue(); CSize8 zrange; zrange.SetSize(0, 0); pValue->GetM(zrange.cx, zrange.cy); double contourStep = (zrange.cy - zrange.cx) / 20; contourStep = AfxGetPublicFunction()->ContourStep(contourStep); CString infoStr; infoStr.Format("%.8lf;5;%.8lf;%.8lf;Layer:\\Contour\\Mark;Layer:\\Contour\\Other", contourStep, zrange.cx, zrange.cy); *infoStrAddress = AsciiToUnicodeChar(infoStr.GetBuffer()); return (int)wcslen(*infoStrAddress); } extern "C" __declspec(dllexport) bool GetMeshPointValue(CSigmaView* pView, double ptX, double ptY, double& ptZ) { CPositionList lstMesh; int nCount = pView->m_pDoc->m_pXy->GetElement(DOUBLEFOX_MESH, lstMesh, TRUE); if (nCount < 1 || lstMesh.IsEmpty()) { return false; } POSITION posMesh = nullptr; posMesh = lstMesh.GetHeadPosition(); if (posMesh == nullptr) { return false; } POSITION pt = lstMesh.GetNext(posMesh); CMesh* pMesh = (CMesh*)(pView->m_pDoc->m_pXy->GetAtValue(pt)); ptZ = pMesh->GetValue(ptX, ptY); if (pMesh->IsInRangeZ(ptZ)) { return true; } ptZ = -1E100; return false; } extern "C" __declspec(dllexport) void Sigma_ReleaseInfoStringForCreatingContour(void * pAddress) { delete pAddress; } extern "C" __declspec(dllexport) int Sigma_CreateContour(CSigmaView * pView, char * informationStringForCreatingContour) { if (informationStringForCreatingContour == 0) return -1; COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CItemMesh im(pView->m_pDoc); im.CreateContour(pOne, informationStringForCreatingContour); //char * pInfo = UnicodeToAscii(informationStringForCreatingContour); /* CItemMesh * itemMesh = new CItemMesh(pView->m_pDoc); COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); itemMesh->CreateContour(pView, pOne); */ return 1; } extern "C" __declspec(dllexport) int Sigma_SmoothSurface(CSigmaView * pView, double coefficient, int smoothNumber) { COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CItemMesh im(pView->m_pDoc); if (!im.GridSmooth(pOne, coefficient, smoothNumber)) { return -1; } return 1; } extern "C" __declspec(dllexport) int Sigma_GridNormalization(CSigmaView* pView) { COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CItemMesh im(pView->m_pDoc); if (!im.GridNormalization(pOne)) { return -1; } return 1; } extern "C" __declspec(dllexport) int Sigma_GridGenerationBoundary(CSigmaView* pView) { COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CItemMesh im(pView->m_pDoc); if (!im.GridGenerationBoundary(pOne)) { return -1; } return 1; } extern "C" __declspec(dllexport) int Sigma_RBFGridExpansion(CSigmaView* pView, int dx_left, int dx_right, int dy_top, int dy_bottom, int maskRadius, double smoothing, int neighbors, int rbfType, int step) { COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CItemMesh im(pView->m_pDoc); if (!im.RBFGridExpansion(pOne, dx_left, dx_right, dy_top, dy_bottom, maskRadius, smoothing, neighbors, rbfType, step)) { return -1; } return 1; } extern "C" __declspec(dllexport) int Sigma_IDWGridExpansion(CSigmaView* pView, int dx_left, int dx_right, int dy_top, int dy_bottom, int maskRadius, int k, int p, int step) { COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return -1; CItemMesh im(pView->m_pDoc); if (!im.IDWGridExpansion(pOne, dx_left, dx_right, dy_top, dy_bottom, maskRadius, k, p, step)) { return -1; } return 1; } extern "C" __declspec(dllexport) void EditGridNode(CSigmaView* pView, HDC hdc, POSITION elementPtr) { //CItemMesh itemMesh(pView->m_pDoc); //itemMesh.SetPos(elementPtr); //itemMesh.EditNode(pView, pView->m_client); CItemMesh * pItemMesh = GetItemMesh(pView); if (pItemMesh == nullptr) return; if (pView->m_pDoc->m_pXy->GetElementType(elementPtr) != DOUBLEFOX_MESH) { return; } CDC *pDC = CDC::FromHandle(hdc); pItemMesh->SetPos(elementPtr); pItemMesh->EditNode(pView, pDC, pView->m_client); } extern "C" __declspec(dllexport) bool MeshFindNodeLocation(CSigmaView* pView, HDC hdc, int mouseX, int mouseY, int& locationX, int& locationY) { CItemMesh * pItemMesh = GetItemMesh(pView); if (pItemMesh == nullptr) false; CPoint point; point.x = mouseX; point.y = mouseY; CDC *pDC = CDC::FromHandle(hdc); bool bFind = pItemMesh->FindNodeLocation(pDC, point, locationX, locationY); return bFind; } extern "C" __declspec(dllexport) void MeshOnMouseMove(CSigmaView* pView, HDC hdcMem, POSITION elementPtr, int mouseX, int mouseY) { CItemMesh * pItemMesh = GetItemMesh(pView); if (pItemMesh != nullptr) { CPoint pt; pt.x = mouseX; pt.y = mouseY; CDC *pDC = CDC::FromHandle(hdcMem); pView->m_pDoc->GetDC().Create(pDC); pItemMesh->OnMouseMove(pDC, 0, pt); } } extern "C" __declspec(dllexport) bool GridPointNoExist(CSigmaView* pView, POSITION elementPtr, int mouseX, int mouseY) { CItemMesh * pItemMesh = GetItemMesh(pView); if (pItemMesh != nullptr) { CPoint pt; pt.x = mouseX; pt.y = mouseY; return pItemMesh->GridPointNoExist(0, pt); } return FALSE; } extern "C" __declspec(dllexport) int GetGridValue(CSigmaView* pView, POSITION elementPtr, int mouseX, int mouseY, BYTE* gridWndValue) { CItemMesh * pItemMesh = GetItemMesh(pView); if (pItemMesh != nullptr) { CPoint pt; pt.x = mouseX; pt.y = mouseY; CString strValue = pItemMesh->GetGridValue(0, pt); int nLen = strValue.GetLength(); memcpy(gridWndValue, strValue.GetBuffer(0), nLen); return nLen; } return 0; } extern "C" __declspec(dllexport) int SetZOfGridPoint(CSigmaView* pView, double z, int row, int column) { CItemMesh * pItemMesh = GetItemMesh(pView); if (pItemMesh == 0) return -1; if (pItemMesh->SetZOfGridPoint(z, row, column)) { return 1; } return -1; } extern "C" __declspec(dllexport) StatisticsGraph * StatisticsGraph_Create(CSigmaView * pView) { CHistogramStat * pStat = new CHistogramStat(); COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return 0; CMesh* pMesh = (CMesh*)pOne->GetValue(); StatisticsGraph * statisticsGraph = new StatisticsGraph(); statisticsGraph->pStat = pStat; statisticsGraph->pMesh = pMesh; statisticsGraph->pItemMesh = new CItemMesh(pView->m_pDoc); statisticsGraph->pItemMesh->Histogram(); statisticsGraph->pItemMesh->SetPos(pView->GetSelectedOnePosition(DOUBLEFOX_MESH)); CRect rect(0, 0, 300, 300); statisticsGraph->graphOutRect = rect; InitStatisticsGraph(statisticsGraph); return statisticsGraph; } extern "C" __declspec(dllexport) void StatisticsGraph_Release(StatisticsGraph * graph) { if (graph != 0) delete graph; } extern "C" __declspec(dllexport) void StatisticsGraph_Draw(CSigmaView * pView, StatisticsGraph * graph, HDC hdc, int graphWidth, int graphHeight) { if (graph == 0) return; CDC * pDC = CDC::FromHandle(hdc); if (pDC == nullptr) return; COne* pOne = pView->GetSelectedOne(DOUBLEFOX_MESH); if (pOne == 0) return; CMesh* pMesh = (CMesh*)pOne->GetValue(); CRect rt(0, 0, graphWidth, graphHeight); CBrush brush; COLORREF white = RGB(255, 255, 255); brush.CreateSolidBrush(white); pDC->FillRect(&rt, &brush); graph->graphOutRect = rt; InitStatisticsGraph(graph); graph->pStat->SetPenWidth(2); graph->pStat->Draw(pDC, &(pMesh->color), rt); // &graph->pMesh->color //CDC * pDCDrawer = CDC::FromHandle(hdcDrawer); //pView->m_pDoc->m_xyDC.Create(pDCDrawer); //wrapper->pItemMesh->SetHistogramRange(-1562.89920, -1547.6952339619); //wrapper->pItemMesh->OnDraw(&pView->m_pDoc->m_xyDC); } extern "C" __declspec(dllexport) void StatisticsGraph_DrawRangeForMesh(CSigmaView * pView, StatisticsGraph * graph, HDC hdcDrawer, double zMin, double zMax) { CDC * pDCDrawer = CDC::FromHandle(hdcDrawer); pView->m_pDoc->m_xyDC.Create(pDCDrawer); graph->pItemMesh->SetHistogramRange(zMin, zMax); graph->pItemMesh->OnDraw(&pView->m_pDoc->m_xyDC); } extern "C" __declspec(dllexport) int StatisticsGraph_GetSelectedRange(StatisticsGraph * graph, int left, int right, double * z1, double * z2) { if (left < 0 || right < 0 || graph == 0) { return -1; } if (left > right) { int dt = left; left = right; right = dt; } int m_num = graph->pStat->GetSize(); double* m_pz = graph->pStat->m_pz; int x = left/2; int y = right/2; if (x < 0) x = 0; if (x > m_num - 1) x = m_num - 1; if (y < 0) y = 0; if (y > m_num - 1) y = m_num - 1; double delt = m_pz[1] - m_pz[0]; *z1 = m_pz[x]; *z2 = m_pz[y]; if (left % 2 > 0) *z1 += delt * 0.5; if (right % 2 > 0) *z2 += delt * 0.5; return 1; } extern "C" __declspec(dllexport) void StatisticsGraph_CalculateGraphRange(StatisticsGraph * graph, double z1In, double z2In, int * leftOut, int * rightOut) { if (z1In > z2In) { double t = z1In; z1In = z2In; z2In = t; } double zmin = graph->pStat->zmin; double zmax = graph->pStat->zmax; int m_num = graph->pStat->GetSize(); double* m_pz = graph->pStat->m_pz; double delt = m_pz[1] - m_pz[0]; //z值范围 int dz = (int)((z1In - zmin) / delt); *leftOut = dz * 2 + int((z1In - zmin) / delt - dz + 0.5); dz = (int)((z2In - zmin) / delt); *rightOut = dz * 2 + int((z2In - zmin) / delt - dz + 0.5); } extern "C" __declspec(dllexport) int StatisticsGraph_DeleteRange(StatisticsGraph * graph, int left, int right) { if (graph == 0) return -1; double z1 = 0; double z2 = 0; if (StatisticsGraph_GetSelectedRange(graph, left, right, &z1, &z2) == -1) return -1; graph->pItemMesh->SetHistogramRange(z1, z2); if (graph->pItemMesh->DeleteSelected() <= 0) return 0; if (graph->pStat->m_pn == NULL) return 0; //graph->pItemMesh->SetHistogramRange(z1, z2); int i = graph->pStat->PositionValueIndex(z1); int j = graph->pStat->PositionValueIndex(z2); if (i < 0) i = 0; if (j < 0) j = 0; if (j > graph->pStat->m_num - 1) j = graph->pStat->m_num - 1; for (int n = i; n <= j; n++) graph->pStat->m_pn[n] = 0; return 1; } extern "C" __declspec(dllexport) int StatisticsGraph_GetRange(StatisticsGraph * graph, double * xMinOut, double * xMaxOut, double * yMinOut, double * yMaxOut, int * pointerCount) { if (graph == 0) return -1; *xMinOut = graph->pStat->zmin; *xMaxOut = graph->pStat->zmax; *yMinOut = 0; *yMaxOut = graph->pStat->GetMaxStatCount(); *pointerCount = graph->pStat->GetSize(); return 1; } extern "C" __declspec(dllexport) int StatisticsGraph_GetZValue(StatisticsGraph * graph, int index, double * v) { if (graph == 0) return -1; *v = graph->pStat->m_pz[index]; return 1; } extern "C" __declspec(dllexport) void StatisticsGraph_SetZValueOfNodeSelected(StatisticsGraph * graph, double v) { graph->pItemMesh->SetZValueOfNodeSelected(v); InitStatisticsGraph(graph); } extern "C" __declspec(dllexport) void StatisticsGraph_GetAreaAndValueForSelected(StatisticsGraph * graph, double minZ, double maxZ, double * areaOut, double * volumeOut) { graph->pItemMesh->GetAreaAndValueForSelected(minZ, maxZ, areaOut, volumeOut); } static void InitStatisticsValue(CMesh* pMesh, CHistogramStat * pStat) { long numx, numy; int i, j; pMesh->GetNumber(numx, numy); pStat->ClearStatState(); #pragma omp parallel for for (i = 0; i < numx; i++) { for (j = 0; j < numy; j++) { double z = pMesh->GetValue(i, j); // 性能瓶颈之一 if (!pMesh->IsInRangeZ(z)) continue; #pragma omp critical { pStat->StatAdd(z); // 性能瓶颈之二,不知道能不能并行,先保守一点,认为是不能并行的 } } } } static void InitStatisticsGraph(StatisticsGraph * statisticsGraph) { if (statisticsGraph == NULL || statisticsGraph->pMesh == NULL) return; double zmin = 0; double zmax = 0; statisticsGraph->pMesh->GetM(zmin, zmax); statisticsGraph->pStat->SetValueRange(zmin, zmax); int num = statisticsGraph->graphOutRect.Width() / 2 - 1; if (num <= 1) num = 2; if (!statisticsGraph->pStat->CreateStat(zmin, zmax, num)) return; InitStatisticsValue(statisticsGraph->pMesh, statisticsGraph->pStat); } // 基于统计直方图计算分位数对应的 Z 值 double GetValueFromStat(CHistogramStat* pStat, double percentile) { if (pStat == nullptr || pStat->m_pn == nullptr) return 0; if (percentile <= 0) return pStat->zmin; if (percentile >= 1.0) return pStat->zmax; int num = pStat->GetSize(); // 统计桶的数量 long long totalCount = 0; // 1. 获取总样本数 for (int i = 0; i < num; i++) { totalCount += pStat->m_pn[i]; } if (totalCount == 0) return pStat->zmin; // 2. 查找累积分布达到目标的桶 long long targetCount = (long long)(totalCount * percentile); long long currentSum = 0; for (int i = 0; i < num; i++) { currentSum += pStat->m_pn[i]; if (currentSum >= targetCount) { // m_pz 存储了每个桶对应的 Z 值刻度 return pStat->m_pz[i]; } } return pStat->zmax; } extern "C" __declspec(dllexport) int Sigma_GetCalculatedAnchors(StatisticsGraph* graph, int mode, int n, double* outValues) { if (graph == nullptr || graph->pStat == nullptr || graph->pMesh == nullptr || n < 2) return -1; graph->pMesh->color.GetColor(); // 使用您提供的代码获取网格的全局极值 double zMin, zMax; graph->pMesh->GetM(zMin, zMax); // 模式定义:1-等距, 2-分位数, 3-截尾等距, 4-截尾分位数 if (mode == 1) { // 等距模式 for (int i = 0; i < n; i++) outValues[i] = zMin + (double)i * (zMax - zMin) / (n - 1); } else if (mode == 2) { // 分位数模式 for (int i = 0; i < n; i++) outValues[i] = GetValueFromStat(graph->pStat, (double)i / (n - 1)); } else if (mode == 3 || mode == 4) { // 截尾模式 (取数据主体的 2% - 98% 范围) double pStart = GetValueFromStat(graph->pStat, 0.02); double pEnd = GetValueFromStat(graph->pStat, 0.98); for (int i = 0; i < n; i++) { if (mode == 3) // 截尾等距 outValues[i] = pStart + (double)i * (pEnd - pStart) / (n - 1); else // 截尾分位数 outValues[i] = GetValueFromStat(graph->pStat, 0.02 + (double)i * 0.96 / (n - 1)); } } // 强制首尾对齐全局范围,防止计算漂移 outValues[0] = zMin; outValues[n - 1] = zMax; return 1; } // 更新网格颜色映射表的函数 extern "C" __declspec(dllexport) void Sigma_ApplyColorScale(CSigmaView* pView, StatisticsGraph* graph, ColorScaleEntry* entries, int count) { if (graph == nullptr || graph->pMesh == nullptr || entries == nullptr) return; //graph->pMesh->color.Clear(); CArray ColorList; for (int i = 0; i < count; i++) { CColorItem colorMesh; // 恢复成你原本最稳妥的传参方式,逐通道强转 BYTE colorMesh.SetColor( (BYTE)entries[i].r, (BYTE)entries[i].g, (BYTE)entries[i].b ); colorMesh.z = entries[i].z; colorMesh.m_bContinue = (entries[i].isContinue != 0); // int 转 bool ColorList.Add(colorMesh); } //记录网格参数 不记录网格 回退 COne* pOneMesh = pView->m_pDoc->m_pXy->CreateOne(graph->pMesh, DOUBLEFOX_MESH); auto pAction = std::make_unique(pView->m_pDoc, IDS_STRING_TOOLBAR_EDIT); pAction->BackupOldArguments(pOneMesh); double zMin, zMax; graph->pMesh->GetM(zMin, zMax); graph->pMesh->color.SetZRange(zMin, zMax); graph->pMesh->color.SetColor(ColorList); graph->pMesh->UpdateColorRuler(); graph->pMesh->GetBitmap(); pAction->BackupNewArguments(); pView->m_pDoc->SetActionItem(pAction.release()); } // 获取当前网格中所有色标项的颜色(不含 Z 值) extern "C" __declspec(dllexport) int Sigma_GetMeshCurrentColors(StatisticsGraph* graph, int* outColors, int maxCount, int* colorCountList, int& listCount) { if (graph == nullptr || graph->pMesh == nullptr) return 0; CArray colorList; graph->pMesh->color.GetColor(colorList); listCount = (int)colorList.GetSize(); // 如果 colorCountList 不为空,才进行填充 if (colorCountList != nullptr) { for (int i = 0; i < listCount; i++) { colorCountList[i] = (int)colorList[i].GetColor(); } } // 处理特殊平均值(锚点颜色) int actualCount = (listCount > maxCount) ? maxCount : listCount; if (outColors != nullptr) { for (int i = 0; i < actualCount; i++) { outColors[i] = (int)colorList[i].GetColor(); } } return actualCount; }