// AppDataCEIpCurveGraphView.cpp : implementation file // #include "stdafx.h" #include "geomative.h" #include "AppDataCEIpCurveGraphView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAppDataCEIpCurveGraphView extern void get_fit_equation(double x[],double y[],int n,double a[],int m,double dt[]); extern double get_fit_equation_value(double x, double a[], int m); IMPLEMENT_DYNCREATE(CAppDataCEIpCurveGraphView, CView) CAppDataCEIpCurveGraphView::CAppDataCEIpCurveGraphView() { m_fMaxAbsV = 0.0; m_iCXOffset = 55; m_iCYOffset = 35; m_pPoint = NULL; m_pPointTwo = NULL; m_pFillTWPt1 = NULL; m_pFillTWPt2 = NULL; m_iPtNum = 0; m_dX1Average = 0; m_dX2Average = 0; m_dPeriodInfo = 0; m_dChrVoltage1 = 0; m_dChrVoltage2 = 0; memset(m_dCoffient1, 0, sizeof(m_dCoffient1)); memset(m_dCoffient2, 0, sizeof(m_dCoffient2)); m_vtTimeWin.clear(); } CAppDataCEIpCurveGraphView::~CAppDataCEIpCurveGraphView() { ClearPoint(); } BEGIN_MESSAGE_MAP(CAppDataCEIpCurveGraphView, CView) //{{AFX_MSG_MAP(CAppDataCEIpCurveGraphView) // NOTE - the ClassWizard will add and remove mapping macros here. ON_WM_MOUSEACTIVATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAppDataCEIpCurveGraphView drawing void CAppDataCEIpCurveGraphView::OnDraw(CDC* pDC) { CDocument* pDoc = GetDocument(); // TODO: add draw code here if (m_dPeriodInfo < 1) { return; } if (0 != m_iPtNum) { DrawEX(pDC); DrawLY(pDC); DrawLine(pDC); } } ///////////////////////////////////////////////////////////////////////////// // CAppDataCEIpCurveGraphView diagnostics #ifdef _DEBUG void CAppDataCEIpCurveGraphView::AssertValid() const { CView::AssertValid(); } void CAppDataCEIpCurveGraphView::Dump(CDumpContext& dc) const { CView::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CAppDataCEIpCurveGraphView message handlers int CAppDataCEIpCurveGraphView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT msg) { return APP_SUCCESS; } void CAppDataCEIpCurveGraphView::DrawLine(CDC* const pDC) { CPen lPen(PS_SOLID, 1, RGB(30, 200, 30)); CPen* pOldLPen = NULL; pOldLPen = pDC->SelectObject(&lPen); int iIndex = (int)VAL_ZERO; // iIndex = (int)VAL_ZERO; int nPtNumber = 4 * m_iPtNum; pDC->MoveTo(*(m_pPoint + iIndex)); while (iIndex < nPtNumber) { pDC->LineTo(*(m_pPoint + iIndex)); pDC->SetPixel(*(m_pPoint+iIndex), RGB(0xFF, 0x00, 0x00)); iIndex++; } iIndex = 0; pDC->MoveTo(*(m_pPointTwo + iIndex)); while (iIndex < nPtNumber) { pDC->LineTo(*(m_pPointTwo + iIndex)); pDC->SetPixel(*(m_pPointTwo+iIndex), RGB(0xFF, 0x00, 0x00)); iIndex++; } //开始填充窗口的部分 CPen lFillTWPen(PS_SOLID, 1, RGB(192,192,192)); pDC->SelectObject(&lFillTWPen); CString strMInfo; int nMIndex = 0; for (int i = 0; i < m_vtTimeWin.size()*(FILL_TIMEWIN_NUM+1); i++) { pDC->MoveTo(m_pFillTWPt1[i]); pDC->LineTo(m_pFillTWPt2[i]); //填充序号标识符 if (0 == i%(FILL_TIMEWIN_NUM+1)) { strMInfo.Empty(); strMInfo.Format(_T("M%d"),nMIndex); pDC->DrawText(strMInfo, CRect(m_pFillTWPt1[i].x, m_pFillTWPt1[i].y - 14, m_pFillTWPt1[i].x+20, m_pFillTWPt1[i].y-2), DT_SINGLELINE | DT_VCENTER | DT_LEFT); nMIndex++; } } pDC->SelectObject(pOldLPen); } void CAppDataCEIpCurveGraphView::DrawEX(CDC* const pDC) { CString szLabel = _T(""); pDC->MoveTo(m_iCXOffset - 1, m_iCYOffset + 150); pDC->LineTo(m_iCXOffset + 410, m_iCYOffset + 150); pDC->MoveTo(m_iCXOffset + 408, m_iCYOffset + 150); pDC->LineTo(m_iCXOffset + 403, m_iCYOffset + 147); pDC->MoveTo(m_iCXOffset + 408, m_iCYOffset + 150); pDC->LineTo(m_iCXOffset + 403, m_iCYOffset + 153); szLabel.Empty(); szLabel = _T("T"); pDC->DrawText(szLabel, CRect(m_iCXOffset + 415, m_iCYOffset + 143, m_iCXOffset + 445, m_iCYOffset + 157), DT_SINGLELINE | DT_VCENTER | DT_LEFT); // pDC->LineTo(m_iCXOffset + 400 + 10, m_iCYOffset + 300 / 2 - 5); } void CAppDataCEIpCurveGraphView::DrawLY(CDC* const pDC) { CPen penDot(PS_DOT, 1, RGB(180, 180, 180)); CPen* pPenOld = NULL; CFont fontEX; CFont* pFontOldEX = NULL; CString szLabel = _T(""); int iIndex = (int)VAL_ZERO; szLabel.Empty(); szLabel = _T("V(mV)"); pDC->DrawText(szLabel, CRect(m_iCXOffset - 20, m_iCYOffset - 28, m_iCXOffset + 20, m_iCYOffset - 8), DT_SINGLELINE | DT_VCENTER | DT_CENTER); pDC->MoveTo(m_iCXOffset - 1, m_iCYOffset); pDC->LineTo(m_iCXOffset - 1, m_iCYOffset + 300); fontEX.CreatePointFont(80, _T("Tahoma")); pFontOldEX = pDC->SelectObject(&fontEX); iIndex = (int)VAL_ZERO; while (iIndex < 11) { //纵轴上的小短线 pDC->MoveTo(m_iCXOffset - 1, m_iCYOffset + 30 * iIndex); pDC->LineTo(m_iCXOffset - 6, m_iCYOffset + 30 * iIndex); if (5 != iIndex) { //图像后面的虚线 pPenOld = pDC->SelectObject(&penDot); pDC->MoveTo(m_iCXOffset - 1, m_iCYOffset + 30 * iIndex); pDC->LineTo(m_iCXOffset + 400, m_iCYOffset + 30 * iIndex); pDC->SelectObject(pPenOld); } //纵轴小短线旁边的坐标数字 szLabel.Empty(); szLabel.Format(_T("%d"), m_iMaxYScale - (m_iMaxYScale / 5) * iIndex); pDC->DrawText(szLabel, CRect(m_iCXOffset - 35, m_iCYOffset + iIndex * 30 - 5, m_iCXOffset - 5, m_iCYOffset + iIndex * 30 + 5), DT_SINGLELINE | DT_VCENTER | DT_RIGHT); iIndex++; } fontEX.DeleteObject(); pDC->SelectObject(pFontOldEX); } int CAppDataCEIpCurveGraphView::CoordinateMapping(float fValue, float fMappingRange, int MappingFactor) { float fUnit = 0.0; float fMValue = 0.0; fUnit = (float)(fMappingRange / MappingFactor); fMValue = fValue / fUnit; return (int)ceilf(fMValue); } void CAppDataCEIpCurveGraphView::CalculatePointCoo() { CPoint* pPoint = NULL; float fXValue = 0.0; float fYValue = 0.0; CString szValue = _T(""); int iIndex = (int)VAL_ZERO; CalculateMaxScale(); ClearPoint(); float fXUnit = 1.0*400/m_iMaxXScale; float fYUnit = 1.0*150/m_iMaxYScale; int nPtNumber = 0; //读m_saOrgDataOne中的数据并绘图 if (m_iPtNum > 0) { //计算第一次放电过程的数据 nPtNumber = 4 * m_iPtNum; //将所需要画的点设置为原来的4倍 double dSplit = m_dPeriodInfo/(4*nPtNumber-1); m_pPoint = new POINT[nPtNumber]; iIndex = (int)0; while (iIndex < nPtNumber) { szValue.Empty(); fXValue = dSplit * iIndex; (m_pPoint+iIndex)->x = m_iCXOffset + (int)ceilf(fXValue * fXUnit); //进行转换的目的是因为m_iCYOffset是Y轴的最高点,而视图的基准点在左上角 fYValue = (float)this->m_iMaxYScale - get_fit_equation_value(fXValue - m_dX1Average, m_dCoffient1, m_iPtNum - 1); (m_pPoint+iIndex)->y = m_iCYOffset + (int)ceilf(fYValue * fYUnit); iIndex++; } //计算第二次放电过程的数据 nPtNumber = 4 * m_iPtNum; //将所需要画的点设置为原来的4倍 m_pPointTwo = new POINT[nPtNumber]; iIndex = (int)0; while (iIndex < nPtNumber) { fXValue = iIndex * dSplit; (m_pPointTwo+iIndex)->x = m_iCXOffset + (int)ceilf(fXValue * fXUnit); fYValue = fabs(get_fit_equation_value(fXValue - m_dX2Average, m_dCoffient2, m_iPtNum - 1)); (m_pPointTwo+iIndex)->y = m_iCYOffset + 150 + (int)ceilf(fYValue * fYUnit); iIndex++; } } //将划分为8等分进行阴影线的划 int nFillSegNum = FILL_TIMEWIN_NUM; int nSigFillPtNum = nFillSegNum+1;//点数比段数多1 m_pFillTWPt1 = new POINT[m_vtTimeWin.size() * nSigFillPtNum]; m_pFillTWPt2 = new POINT[m_vtTimeWin.size() * nSigFillPtNum]; memset(m_pFillTWPt1, 0, sizeof(POINT)*m_vtTimeWin.size() * nSigFillPtNum); memset(m_pFillTWPt2, 0, sizeof(POINT)*m_vtTimeWin.size() * nSigFillPtNum); for (int i =0; i < m_vtTimeWin.size(); i++) { float fSigSplit = (float)m_vtTimeWin[i].nTWWidth/nFillSegNum; //计算第一次放电过程的X和Y值 int j = 0; for (j = 0; j < nSigFillPtNum; j++) { if (nFillSegNum == j)//这样做是为了防止除8,又乘8之后,不一定精确的等于原来的值得问题 fXValue = m_vtTimeWin[i].nTWStartPos + m_vtTimeWin[i].nTWWidth; else fXValue = m_vtTimeWin[i].nTWStartPos + j*fSigSplit; m_pFillTWPt1[i*nSigFillPtNum+j].x = m_iCXOffset + (int)ceilf(fXValue * fXUnit); fYValue = (float)this->m_iMaxYScale - get_fit_equation_value(fXValue - m_dX1Average, m_dCoffient1, m_iPtNum - 1); m_pFillTWPt1[i*nSigFillPtNum+j].y = m_iCYOffset + (int)ceilf(fYValue * fYUnit); } //计算第二次放电过程的Y值 for (j = 0; j < nSigFillPtNum; j++) { if (nFillSegNum == j)//这样做是为了防止除8,又乘8之后,不一定精确的等于原来的值得问题 fXValue = m_vtTimeWin[i].nTWStartPos + m_vtTimeWin[i].nTWWidth; else fXValue = m_vtTimeWin[i].nTWStartPos + j*fSigSplit; m_pFillTWPt2[i*nSigFillPtNum+j].x = m_iCXOffset + (int)ceilf(fXValue * fXUnit); fYValue = fabs(get_fit_equation_value(fXValue - m_dX2Average, m_dCoffient2, m_iPtNum - 1)); m_pFillTWPt2[i*nSigFillPtNum+j].y = m_iCYOffset + 150 + (int)ceilf(fYValue * fYUnit); } } // //读m_saOrgDataTwo中的数据并绘图 // if (m_saOrgDataTwo.GetSize() > /*4*/0) // { // // m_iPtNumTwo = this->m_saOrgDataTwo.GetSize()/* - 4*/; // nPtNumber = 4 * m_iPtNum; //将所需要画的点设置为原来的4倍 // m_pPointTwo = new POINT[m_iPtNumTwo]; // iIndex = (int)0; // while (iIndex < m_iPtNumTwo) // { // szValue.Empty(); // szValue = this->m_saOrgDataTwo.GetAt(iIndex /*+ 4*/); // // fXValue = (float)iIndex; // (m_pPointTwo+iIndex)->x = m_iCXOffset + this->CoordinateMapping(fXValue, (float)this->m_iMaxXScale, 400); // // fYValue = (float)this->m_iMaxYScale - (float)atof(szValue); // (m_pPointTwo+iIndex)->y = m_iCYOffset + this->CoordinateMapping(fYValue, (float)2 * m_iMaxYScale, 300); // // iIndex++; // } // } } void CAppDataCEIpCurveGraphView::CalculateMaxScale() { m_iMaxXScale = 1.1 * m_dPeriodInfo / 4; //将X轴的最大范围设置为周期的1.15倍 double dTmp = (fabs(m_dChrVoltage1) > fabs(m_dChrVoltage2)) ? fabs(m_dChrVoltage1) : fabs(m_dChrVoltage2); m_iMaxYScale = dTmp * 1.1; // int iFill = (int)VAL_ZERO; // m_iMaxYScale = (int)ceil(this->m_fMaxAbsV); // // iFill = (int)VAL_ZERO; // while (TRUE) // { // if (0.0 == ((m_iMaxYScale + iFill) * 2) % 10) // { // m_iMaxYScale = m_iMaxYScale + iFill; // break; // } // iFill++; // } // // if (this->m_saOrgDataOne.GetSize() > /*4*/0) // { // m_iMaxXScale = this->m_saOrgDataOne.GetSize()/* - 4*/; // } } void CAppDataCEIpCurveGraphView::ClearPoint() { int iIndex = (int)VAL_ZERO; if (m_pPoint) { delete[] m_pPoint; m_pPoint = NULL; } if (m_pPointTwo) { delete[] m_pPointTwo; m_pPointTwo = NULL; } if (m_pFillTWPt1) { delete[] m_pFillTWPt1; m_pFillTWPt1 = NULL; } if (m_pFillTWPt2) { delete[] m_pFillTWPt2; m_pFillTWPt2 = NULL; } } void CAppDataCEIpCurveGraphView::OnInitialUpdate() { CView::OnInitialUpdate(); // TODO: Add your specialized code here and/or call the base class CalculateIpCurve(); CalculatePointCoo(); } void CAppDataCEIpCurveGraphView::CalculateIpCurve() { int nSize = m_saOrgDataOne.GetSize(); m_iPtNum = atoi(m_saOrgDataOne.GetAt(3)); double dSplit = m_dPeriodInfo/(m_iPtNum-1); m_iPtNum = m_iPtNum/4; CString szTmp = _T(""); //取出原始数据第二第四段 double dXData[MAX_DISCHARGE_PT], dYData[MAX_DISCHARGE_PT], dtInfo[MAX_DISCHARGE_PT]; memset(dXData, 0, sizeof(dXData)); memset(dYData, 0, sizeof(dYData)); memset(m_dCoffient1, 0, sizeof(m_dCoffient1)); memset(dtInfo, 0, sizeof(dtInfo)); m_dX1Average = 0; int nIndex; for (nIndex= 0; nIndex < m_iPtNum; nIndex++) { dXData[nIndex] = nIndex * dSplit; //以放电的第一个点的位置为基准进行多项式的计算 m_dX1Average += dXData[nIndex]; dYData[nIndex] = atof(m_saOrgDataOne.GetAt(4 + m_iPtNum + nIndex)); } m_dX1Average = m_dX1Average / m_iPtNum; m_dChrVoltage1 = 0; for (nIndex = 0; nIndex < 3; nIndex++) { m_dChrVoltage1 += atof(m_saOrgDataOne.GetAt(3+m_iPtNum-nIndex)); } m_dChrVoltage1 = m_dChrVoltage1/3; //获取第一段放电的多项式 get_fit_equation(dXData, dYData, m_iPtNum, m_dCoffient1, m_iPtNum-1, dtInfo); //得到第二次放电的的多项式 memset(dXData, 0, sizeof(dXData)); memset(dYData, 0, sizeof(dYData)); memset(m_dCoffient2, 0, sizeof(m_dCoffient2)); memset(dtInfo, 0, sizeof(dtInfo)); //获取采样时窗 for (nIndex= 0; nIndex < m_iPtNum; nIndex++) { dXData[nIndex] = nIndex * dSplit; //以放电的第一个点的位置为基准进行多项式的计算 m_dX2Average += dXData[nIndex]; dYData[nIndex] = atof(m_saOrgDataOne.GetAt(4 + m_iPtNum*3 + nIndex)); } m_dX2Average = m_dX2Average/m_iPtNum; m_dChrVoltage2 = 0; for (nIndex = 0; nIndex < 3; nIndex++) { m_dChrVoltage2 += atof(m_saOrgDataOne.GetAt(3+m_iPtNum-nIndex)); } m_dChrVoltage2 = m_dChrVoltage2/3; //计算第二段的多项式 get_fit_equation(dXData, dYData, m_iPtNum, m_dCoffient2, m_iPtNum-1, dtInfo); // szTmp = m_saOrgDataOne.GetAt((nCount * 3) + 200); // szArrayTwo.Add(szTmp); // //判断X轴上方的线条的那段区间 // int nDis = -1; //区间0代表第一段 1代表第二段 2代表第三段 3代表第四段 // float nResult = 0; // float fNumOne = 0, fNumTwo = 0; // CString szTmp; // // for (int n = 0; n < 4; n++) // { // szTmp = m_saOrgData.GetAt((nCount * n) + (nCount / 3)); // fNumOne = atof(szTmp.GetBuffer(0)); // // szTmp = m_saOrgData.GetAt((nCount * n) + (nCount / 3 * 2)); // fNumTwo = atof(szTmp.GetBuffer(0)); // // if (fNumTwo < 0 || fNumOne < 0) // { // continue; // } // // nResult = fNumOne - fNumTwo; // // if (nResult > 0) // { // nDis = n; // break; // } // } // // if (nDis == -1) // { // nDis = 1; // } // // CStringArray szArray; // // //取出那一段的值 // for(n = 0; n < nCount; n++) // { // if (nCount * nDis + n >= m_saOrgData.GetSize()) // { // break; // } // szTmp = m_saOrgData.GetAt(nCount * nDis + n); // szArray.Add(szTmp); // } // m_saOrgData.RemoveAll(); // m_saOrgData.Copy(szArray); }