Files
coco df489d5640 a
2026-07-03 16:05:30 +08:00

657 lines
17 KiB
C++

// Medium.cpp: implementation of the CMedium class.
//
//////////////////////////////////////////////////////////////////////
#include "Medium.h"
#include <map>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
extern int g_iUILanguage;
CMedium::CMedium()
{
m_iStartPole = 1;
m_iEndPole = 1;
m_mapUniversalLayer.clear();
}
CMedium::CMedium(int iAR)
{
m_iAR = iAR;
m_iStartPole = 1;
m_iEndPole = 1;
m_mapUniversalLayer.clear();
}
CMedium::~CMedium()
{
}
void CMedium::CalculateTdPtLoc(const CRect& vRect, const int& iEAmount, int& iMaxLevel, CRect& lRect, int& iSmWidth, int& iSmHeight, CPtrArray* pTdRecArray)
{
int iTop = 0;
int iBottom = 0;
int iLeft = 0;
int iRight = 0;
int iRectWidth = 0;
int iRectHeight = 0;
iSmWidth = 0;
iSmHeight = 0;
int iLevel = 0;
int iPos = 0;
int iIndex = 0;
int iEOffset = 0;
int iLOffset = 0;
int iNewEAmount = iEAmount;
if (iEAmount%ELECTRODE_AMOUNT_PERCABLE != 0)
{
iNewEAmount =ELECTRODE_AMOUNT_PERCABLE * (1 + iEAmount/ELECTRODE_AMOUNT_PERCABLE);
}
iMaxLevel = this->GetMaxLevelByEAmount(iNewEAmount);
int iXEAmount = (m_iEndPole > m_iStartPole) ? m_iEndPole - m_iStartPole +1 : iEAmount;
lRect = vRect;
//已此时的CRect的中心移动边来缩小输入的rect的大小
lRect.DeflateRect(141, 40, 61, 40);
//返回大于或者等于指定表达式的最小整数,value 如果有小数部分则进一位
//iEAmount为电极的个数,非测点总数,第一层的测点数是最接近电极数的,在倒三角的剖面中
iSmWidth = (int)ceil(lRect.Width()*1.0/iXEAmount);
iSmHeight = (int)ceil(lRect.Height()*1.0/iMaxLevel);
//将iSmWidth变成奇数,那么iSmWidth-1此时将成为偶数,再用它去乘以任何数也都将是偶数
if (fmod((double)iSmWidth, 2.0) == 0.0)
{
iSmWidth++;
}
//由于极端的AM装置中,那么在第一层的最后一个位置,此时AM的点的坐标将会超过X轴的坐标系,
//所以此时要留有一个装置的余量
iRectWidth = iSmWidth+(iSmWidth-1)*(iXEAmount-1);
//iRectWidth = iSmWidth+(iSmWidth-1)*(iEAmount-2);
if (fmod((double)iSmHeight, 2.0) == 0.0)
{
iSmHeight++;
}
//iRectHeight代表所有层数所占用的总的高度
iRectHeight = iSmHeight+(iSmHeight-1)*(iMaxLevel-1);
if (fmod(lRect.Width()-iRectWidth, 2.0) == 0.0)
{
iLeft = (lRect.Width()-iRectWidth)/2;
iRight = (lRect.Width()-iRectWidth)/2;
}
else
{
iLeft = (lRect.Width()-iRectWidth)/2+1;
iRight = (lRect.Width()-iRectWidth)/2;
}
if (fmod(lRect.Height()-iRectHeight, 2.0) == 0.0)
{
iTop = (lRect.Height()-iRectHeight)/2;
iBottom = (lRect.Height()-iRectHeight)/2;
}
else
{
iTop = (lRect.Height()-iRectHeight)/2+1;
iBottom = (lRect.Height()-iRectHeight)/2;
}
lRect.DeflateRect(iLeft, iTop, iRight, iBottom);
CRsp2DTdRecord* pRsp2DTdRecord = NULL;
//iLOffset和iEOffset用来计算中间点和测点之间的偏差
//比如AMN模式中,点在MN的中点位置,此时m_iPosInLevel取得是M点的位置,
//那么iLOffset和iEOffset则用来计算M和中点位置之间的偏差
iEOffset = (int)((iSmWidth-1)*m_fEOffsetR);
iLOffset = (int)((iSmWidth-1)*m_fLOffsetR);
while (iIndex < pTdRecArray->GetSize())
{
pRsp2DTdRecord = (CRsp2DTdRecord*)(pTdRecArray->GetAt(iIndex));
iLevel = pRsp2DTdRecord->m_iLevel-1;
iPos = pRsp2DTdRecord->m_iPosInLevel-1 - m_iStartPole + 1;
pRsp2DTdRecord->m_recPtArea.SetRectEmpty();
pRsp2DTdRecord->m_recPtArea.SetRect(lRect.left+iEOffset+iLOffset*iLevel+(iSmWidth-1)*iPos, lRect.top+(iSmHeight-1)*iLevel,
lRect.left+iEOffset+iLOffset*iLevel+(iSmWidth-1)*iPos+iSmWidth, lRect.top+(iSmHeight-1)*iLevel+iSmHeight-1);
iIndex++;
}
}
void CMedium::SetValidPoleInfo(int iStartPole,int iEndPole)
{
if (iStartPole < 1 || iEndPole <= iStartPole)
{
CString str = _T("");
if (LANG_ZHCN == g_iUILanguage)
{
str.Format(_T("设置开始电极错误.开始电极 = %d, 结束电极 = %d"), iStartPole, iEndPole);
AfxMessageBox(str);
}
else
{
str.Format(_T("Set start pole error.start_pole = %d, end_pole = %d"), iStartPole, iEndPole);
MessageBoxEx(NULL, str, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
m_iStartPole = 1;
m_iEndPole = 1;
return;
}
m_iStartPole = iStartPole;
m_iEndPole = iEndPole;
}
float CMedium::CalculateDepth(float fA, float fFactor)
{
// return (float)(fabs(fB)+fabs(fA))*fFactor;
return 0.0;
}
void CMedium::ReSortPoint(CPtrArray *f_ptr)
{
CSptRecord* pSptRecord = NULL;
int nMidPos = 0; //第一层中点的起始位置
int nWidth = 0; //用于统计第一层有多少个测点
int *nPos = new int[f_ptr->GetSize()];
for (int n = 0;n < f_ptr->GetSize(); n++)
{
pSptRecord = (CSptRecord *)f_ptr->GetAt(n);
if (pSptRecord->m_iLevel == 1)
{
nPos[nWidth] = pSptRecord->m_iTsn; //把对应的TSN保存在数组中方便取出
nWidth++;
}
}
nMidPos = ( nWidth / 2 ) - 1; //将测点分成2个部分进行测试,从上一个斜线方向开始测
int FirStart = 0;
int SecStart = 0;
int Sum = 1; //tsn从1开始
FirStart = 0; //第一部分的起点位置
SecStart = nPos[nMidPos] + 1; //第二部分的起点位置
while(Sum < f_ptr->GetSize())
{
for (FirStart; FirStart < nPos[nMidPos]; )
{
pSptRecord = (CSptRecord *)f_ptr->GetAt(FirStart);
pSptRecord->m_iTsn = Sum;
Sum++;
FirStart++;
if (pSptRecord->m_iLevel == 1)
break;
}
for (SecStart; SecStart < f_ptr->GetSize(); )
{
pSptRecord = (CSptRecord *)f_ptr->GetAt(SecStart - 1); //索引要减1
pSptRecord->m_iTsn = Sum;
Sum++;
SecStart++;
if (pSptRecord->m_iLevel == 1)
break;
}
}
//对数组中的元素全部重新进行排序
int sortTsn = 1;
for (int k = 0; k < f_ptr->GetSize(); k++)
{
pSptRecord = (CSptRecord *)f_ptr->GetAt(k);
if (pSptRecord->m_iTsn != k + 1)
{
for (int n = k + 1; n < f_ptr->GetSize(); n++)
{
pSptRecord = (CSptRecord *)f_ptr->GetAt(n);
if (pSptRecord->m_iTsn == k + 1)
{
f_ptr->InsertAt(k, pSptRecord);
f_ptr->RemoveAt(n + 1); //上一行代码插入一个元素,故 + 1;
break;
}
}
}
}
}
void CMedium::ReSortPoint(CPtrArray *f_ptr, int iRunMethod)
{
if (iRunMethod < 0 || iRunMethod > 2 )
{
CString str = _T("");
if (LANG_ZHCN == g_iUILanguage)
{
str.Format(_T("输入run_method参数错误.value = %d"), iRunMethod);
AfxMessageBox(str);
}
else
{
str.Format(_T("Input run_method parameter error.value = %d"), iRunMethod);
MessageBoxEx(NULL, str, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
return;
}
if (EnSptRunByDisorder == iRunMethod)
{
ReSortPoint(f_ptr);
return;
}
CSptRecord* pSptRecord = NULL;
std::map<STInt2KeyInfo,int> mapOrderInfo;
mapOrderInfo.clear();
STInt2KeyInfo stIntKey;
int i = 0;
int iPtTotalNum = f_ptr->GetSize();
for (i = 0; i < iPtTotalNum; i++)
{
pSptRecord = (CSptRecord *)f_ptr->GetAt(i);
int iMinElecID = 100000;
if (pSptRecord->m_iC1 > 0)
{
iMinElecID = pSptRecord->m_iC1;
}
if (pSptRecord->m_iC2 > 0 && pSptRecord->m_iC2 < iMinElecID)
{
iMinElecID = pSptRecord->m_iC2;
}
if (pSptRecord->m_iP1 > 0 && pSptRecord->m_iP1 < iMinElecID)
{
iMinElecID = pSptRecord->m_iP1;
}
if (pSptRecord->m_iP2 > 0 && pSptRecord->m_iP2 < iMinElecID)
{
iMinElecID = pSptRecord->m_iP2;
}
//如果是滚动的,则取出电极里最小的电极序号作为KEY1,层数作为KEY2
if (EnSptRunByRoll == iRunMethod)
{
stIntKey.iKey1 = iMinElecID;
stIntKey.iKey2 = pSptRecord->m_iLevel;
}
//如果是分层式跑极,则取出层数作为KEY1,电极里最小的电极序号作为KEY2,
//因为在同一层里,最小电极也是在一直从做向右滚动的
else
{
stIntKey.iKey1 = pSptRecord->m_iLevel;
stIntKey.iKey2 = iMinElecID;
}
mapOrderInfo[stIntKey] = i;
}
if (iPtTotalNum != mapOrderInfo.size())
{
CString str = _T("");
if (LANG_ZHCN == g_iUILanguage)
{
str.Format(_T("由于重叠点的存在,对点误差进行排序.总电极数 = %d,排序电极数 = %d."), iPtTotalNum, mapOrderInfo.size());
AfxMessageBox(str);
}
else
{
str.Format(_T("Sort point error because of overlap point.TotalPtNum = %d,SortPtNum = %d."), iPtTotalNum, mapOrderInfo.size());
MessageBoxEx(NULL, str, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
return;
}
CPtrArray NewPtArr;
NewPtArr.RemoveAll();
std::map<STInt2KeyInfo,int>::iterator iter = mapOrderInfo.begin();
int iTsn = 0;
for (; iter != mapOrderInfo.end(); iter++)
{
iTsn++;
pSptRecord = (CSptRecord*)f_ptr->GetAt(iter->second);
pSptRecord->m_iTsn = iTsn;
NewPtArr.Add(pSptRecord);
}
f_ptr->RemoveAll();
for (i = 0; i < NewPtArr.GetSize(); i++)
{
f_ptr->Add(NewPtArr.GetAt(i));
}
if (EnSptRunByLayer == iRunMethod)
{
ResirtPointAgainByLevel(f_ptr);
}
}
void CMedium::ResirtPointAgainByLevel(CPtrArray *f_ptr)
{
//如果是AM装置或者偶极-偶极装置,则不用进行再排序
if (6 == m_iAR || 9 == m_iAR || 4 == m_iAR || 16 == m_iAR || m_iAR > 39)
{
return;
}
int iACoffient = 3;
int iSepCoffient = 0;
CString strErr = _T("");
if (m_iAR >= 1 && m_iAR <= 3)
{
iSepCoffient = 3;
}
else if (11 == m_iAR || 39 == m_iAR || AR_WENNER_SCH_BASIC == m_iAR)
{
iSepCoffient = 2;
}
else if (5 == m_iAR)
{
iACoffient = 2;
iSepCoffient = 2;
}
else
{
if (LANG_ZHCN == g_iUILanguage)
{
strErr.Format(_T("未知装置类型(%d)"), m_iAR);
AfxMessageBox(strErr);
}
else
{
strErr.Format(_T("Unknow medium type(%d) for resort point by lever."), m_iAR);
MessageBoxEx(NULL, strErr, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
return;
}
CPtrArray OrderArr;
OrderArr.RemoveAll();
//此时的f_ptr已经是按照层数来进行排序的
int iTsn = 0;
for (int iLayer = 1; iLayer <= 3; iLayer++)
{
//在这里加1是因为iSepVal指的是中间间隔的点,而不包括起点在内
int iSepVal = iACoffient + (iLayer-1)*iSepCoffient +1;
int iStartIndex = OrderArr.GetSize()+1;
for (int i = 1; i <= iSepVal; i++)
{
int iIndex = iStartIndex + (i-1);
while(TRUE)
{
if (iIndex > f_ptr->GetSize())
{
// strErr.Empty();
// strErr.Format(_T("Resort point by lever overflow.currenr_index = %d, max_point_number = %d"), iIndex, f_ptr->GetSize());
// AfxMessageBox(strErr);
// return;
break;
}
CSptRecord *pt = (CSptRecord*)f_ptr->GetAt(iIndex-1);
if (pt->m_iLevel != iLayer)
{
break;
}
pt->m_iTsn = ++iTsn;
OrderArr.Add(pt);
iIndex += iSepVal;
}
}
}
//此时将排序后前三层的节点的节点进行重新的赋值到原来的链表当中去
for (int n =0; n < OrderArr.GetSize(); n++)
{
f_ptr->SetAt(n, OrderArr.GetAt(n));
}
}
bool CMedium::AddSptToUniLayer(int iA, int iB, int iM, int iN)
{
int iMin = 100000, iMax = 0;
int iDataArr[4] = {iA, iB, iM, iN};
for (int i = 0; i < 4; i++)
{
if (iDataArr[i] > 0)
{
if (iDataArr[i] > iMax)
{
iMax = iDataArr[i];
}
if (iDataArr[i] < iMin)
{
iMin = iDataArr[i];
}
}
}
int iLayer = iMax - iMin;
if (iLayer < 1 || iMin < 1 || iMax < 1)
{
CString strErr = _T("");
if (LANG_ZHCN == g_iUILanguage)
{
strErr.Format(_T("脚本层信息错误.最小值 = %d,最大值 = %d, ABMN = %d,%d,%d,%d"), iMin, iMax, iA, iB, iM, iN);
AfxMessageBox(strErr);
}
else
{
strErr.Format(_T("Script layer information error.MinVal = %d,MaxVal = %d, Index = %d,%d,%d,%d"), iMin, iMax, iA, iB, iM, iN);
MessageBoxEx(NULL, strErr, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
return false;
}
m_mapUniversalLayer[iLayer] = 1;
return true;
}
void CMedium::AddSptToUniLayerFinish()
{
int i = 0;
std::map<int,int>::iterator iter = m_mapUniversalLayer.begin();
for (; iter != m_mapUniversalLayer.end(); iter++)
{
iter->second = ++i;
}
}
int CMedium::QuerySptLayerFromUni(int iA, int iB, int iM, int iN)
{
int iMin = 100000, iMax = 0;
int iDataArr[4] = {iA, iB, iM, iN};
for (int i = 0; i < 4; i++)
{
if (iDataArr[i] > 0)
{
if (iDataArr[i] > iMax)
{
iMax = iDataArr[i];
}
if (iDataArr[i] < iMin)
{
iMin = iDataArr[i];
}
}
}
int iLayer = iMax - iMin;
if (iLayer < 1 || iMin < 1 || iMax < 1)
{
CString strErr = _T("");
if (LANG_ZHCN == g_iUILanguage)
{
strErr.Format(_T("查询脚本层信息错误.最小值 = %d,最大值 = %d, ABMN = %d,%d,%d,%d"), iMin, iMax, iA, iB, iM, iN);
AfxMessageBox(strErr);
}
else
{
strErr.Format(_T("Query Spt layer information error.MinVal = %d,MaxVal = %d, Index = %d,%d,%d,%d"), iMin, iMax, iA, iB, iM, iN);
MessageBoxEx(NULL, strErr, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
return 0;
}
std::map<int,int>::iterator iter = m_mapUniversalLayer.find(iLayer);
if (iter == m_mapUniversalLayer.end())
{
return 0;
}
return iter->second;
}
float CMedium::GetUniSptXPos(int iA, int iB, int iM, int iN)
{
//16-39的区间为1维脚本和3维脚本,不支持
//在这里只支持2维脚本
// if (m_iAR > 16 && m_iAR < 39) //2D脚本装置类型
// {
// AfxMessageBox(_T("Universal script only supprot 2D script."));
// return -1;
// }
int iMin = 100000, iMax = 0, iTotalVal = 0;
int iDataArr[4] = {iA, iB, iM, iN};
int iNegativeCnt = 0;//非正整数的个数
for (int i = 0; i < 4; i++)
{
if (iDataArr[i] > 0)
{
if (iDataArr[i] > iMax)
{
iMax = iDataArr[i];
}
if (iDataArr[i] < iMin)
{
iMin = iDataArr[i];
}
iTotalVal += iDataArr[i];
}
else
iNegativeCnt++;
}
//如果全部是正整数(四级装置),则此时iTotalVal表示的是四个数的总和,那么需要剪掉最大的和最小的
if (0 == iNegativeCnt)
return (iTotalVal-iMin-iMax)*1.0/2;
//如果此时是三级装置,那么此时只需要减掉最小值即可
if (1 == iNegativeCnt)
return (iA < 0 ? (iB + iN) : (iA + iN))*1.0/2;
//如果是二级装置,则不需进行再处理
if (2 == iNegativeCnt)
return iTotalVal*1.0/2;
CString strErr;
if (LANG_ZHCN == g_iUILanguage)
{
strErr.Format(_T("GetUniSptXPos错误,负值%d"), iNegativeCnt);
AfxMessageBox(strErr);
}
else
{
strErr.Format(_T("GetUniSptXPos error,number of negative is %d"), iNegativeCnt);
MessageBoxEx(NULL, strErr, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
return -1;
}
bool CMedium::GeneralUniSptInfo(int& iMaxLevel,CPtrArray* pSptRecArr)
{//louis, here how to modify ?
if (m_iAR > 16 && m_iAR < 39) //2D脚本装置类型
{
if (LANG_ZHCN == g_iUILanguage)
AfxMessageBox(_T("通用脚本只支持2D脚本"));
else
MessageBoxEx(NULL, _T("Universal script only supprot 2D script"), STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
return false;
}
//自定义装置不需要计算通用脚本
if (m_iAR == 40)
{
return true;
}
CSptRecord *pSptRecord = NULL;
int iSize = pSptRecArr->GetSize();
int i = 0;
//跨孔和井地井装置都不能进行剖面图的绘画
//根据育杰的要求,跨孔的层数依然要进行保留(added by 20170120)
if (AR_CROSS_HOLE_TYPE == m_iAR || AR_BIPOLE_HOLE_SPT == m_iAR)
{
for (i = 0; i < iSize; i++)
{
pSptRecord = (CSptRecord *)pSptRecArr->GetAt(i);
pSptRecord->m_fSptXPos = 0;
// pSptRecord->m_iLevel = 0;
}
// iMaxLevel = 0;
}
//在这里这些装置由于没有层数信息,所以采用新的通用脚本信息算脚本的层数
else if (m_iAR > 39 && m_iAR < AR_WENNER_SCH_BASIC)//louis ,here is right?
{
ClearUniversalLayer();
for (i = 0; i < iSize; i++)
{
pSptRecord = (CSptRecord *)pSptRecArr->GetAt(i);
pSptRecord->m_fSptXPos = GetUniSptXPos(pSptRecord->m_iC1, pSptRecord->m_iC2, pSptRecord->m_iP1, pSptRecord->m_iP2);
if (!AddSptToUniLayer(pSptRecord->m_iC1, pSptRecord->m_iC2, pSptRecord->m_iP1, pSptRecord->m_iP2))
{
ClearUniversalLayer();
return false;
}
}
AddSptToUniLayerFinish();
for (i = 0; i < iSize; i++)
{
pSptRecord = (CSptRecord *)pSptRecArr->GetAt(i);
pSptRecord->m_iLevel = QuerySptLayerFromUni(pSptRecord->m_iC1, pSptRecord->m_iC2, pSptRecord->m_iP1, pSptRecord->m_iP2);
}
iMaxLevel = QueryMaxLayerFromUni();
}
//如果是之前已经计算了层数,和郑挺确认过层数信息依然沿用原来的所以在这里只需要单独计算X轴的信息即可
//最大层数也沿用之前的最大层数,不做修改
else
{
for (i = 0; i < iSize; i++)
{
pSptRecord = (CSptRecord *)pSptRecArr->GetAt(i);
pSptRecord->m_fSptXPos = GetUniSptXPos(pSptRecord->m_iC1, pSptRecord->m_iC2, pSptRecord->m_iP1, pSptRecord->m_iP2);
}
}
}
bool CMedium::SortMulChannelSpt(CPtrArray* pSptRecArr)
{
if (AR_DIPOLE_POLE_MNB == m_iAR)
return m_sortMulChannelSpt.MultiChannlePtSortForMNB(pSptRecArr);
return m_sortMulChannelSpt.MultiChannlePtSort(pSptRecArr);
}