📄 netlayer.cpp
字号:
pLink.m_fToImp = (float)(nlk->m_fToImp * ( 1 - dRatio ));
m_arrLinks.AddTail( pLink );
nlk->m_nTNode = *nNewNode;
nlk->m_fLength = (float)(nlk->m_fLength * dRatio);
nlk->m_fFromImp = (float)(nlk->m_fFromImp * dRatio);
nlk->m_fToImp = (float)(nlk->m_fToImp * dRatio);
}
return true;
}
//-----------------------------------------------------------------------------------------
int CNetLayer::GetNode( int nLineID, int* nFNode, int* nTNode )
{
*nFNode = -1;
*nTNode = -1;
for ( int i = 0; i<m_arrLinks.GetCount(); i++ )
{
NetLink nl = m_arrLinks.GetAt(m_arrLinks.FindIndex(i));
if(nLineID == nl.m_GeoID )
{
*nFNode = nl.m_nFNode;
*nTNode = nl.m_nTNode;
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------------------
double CNetLayer::Path( int nBeginNode, int nEndNode,
CList<int, int&>* pNodes, BOOL bWeight )
{
if (nBeginNode < 0 || nBeginNode >= m_arrNodes.GetCount())
return -1;
if ( nEndNode < 0 || nEndNode >= m_arrNodes.GetCount())
return -1;
// 如果两个结点相同
if ( nBeginNode == nEndNode )
{
pNodes->AddTail(nBeginNode );
return 0;
}
// 计算nBeginNode到其他所有结点的最短路径
if ( !CalcPath( nBeginNode, nEndNode, bWeight ) )
return -1;
// 提取从nBeginNode到nEndNode的路径
// 从nEndNode向前搜索前趋结点
int nNode;
nNode = nEndNode;
while(TRUE)
{
// 如果没有前趋结点,表示不连通
if ( m_pPath[nNode].m_nPreNode == -1 )
return -1;
// 如果前趋结点为起始结点,路径结束
if ( m_pPath[nNode].m_nPreNode == nBeginNode )
{
pNodes->AddHead( nNode );
break;
}
// 加入中间结点
pNodes->AddHead(nNode );
nNode = m_pPath[nNode].m_nPreNode;
}
// 加入起点
pNodes->AddHead(nBeginNode );
return m_pPath[nEndNode].m_dLength;
}
//-----------------------------------------------------------------------------------------
BOOL CNetLayer::CalcPath(int nNode, int nEndNode, BOOL bWeight )
{
if ( nNode < 0 || nNode >= m_arrNodes.GetCount())
return FALSE;
int i, j, nNodeNum;
int nLink;
byte* pMark = NULL; // 处理标志数组
nNodeNum = m_arrNodes.GetCount();
if ( nNodeNum == 0 )
return TRUE;
pMark = new byte[nNodeNum];
memset(pMark, 0, nNodeNum);
// (1) 初始化
// 初始化路径数组, 类的构造函数会将长度置为-1, 前趋结点为-1
if(m_pPath)
{
delete m_pPath;
m_pPath = NULL;
}
m_pPath = new NetPath[nNodeNum];
// 自身
m_pPath[nNode].m_dLength = 0;
m_pPath[nNode].m_nPreNode = nNode;
// 对于与该结点直接相连的点, 初始化路径长度为连接弧度的阻力
NetNode* nd = &(m_arrNodes.GetAt(m_arrNodes.FindIndex(nNode)));
for ( i = 0; i<nd->m_arrLinks.GetCount(); i++ )
{
NetEdge ng = nd->m_arrLinks.GetAt(nd->m_arrLinks.FindIndex(i));
nLink = ng.nLink;
NetLink nl = m_arrLinks.GetAt(m_arrLinks.FindIndex(nLink));
if(nl.m_nFNode == nNode )
{
// 路径长度, 正向
m_pPath[nl.m_nTNode].m_dLength = bWeight ? nl.m_fFromImp : nl.m_fLength;
// 前趋结点, 如果长度<0, 无前趋结点
if ( m_pPath[nl.m_nTNode].m_dLength < 0 )
m_pPath[nl.m_nTNode].m_nPreNode = -1;
else
m_pPath[nl.m_nTNode].m_nPreNode = nNode;
}
else if(nl.m_nTNode == nNode )
{
// 路径长度, 逆向
m_pPath[nl.m_nFNode].m_dLength = bWeight ? nl.m_fToImp : nl.m_fLength;
// 前趋结点, 如果长度<0, 无前趋结点
if ( m_pPath[nl.m_nFNode].m_dLength < 0 )
m_pPath[nl.m_nFNode].m_nPreNode = -1;
else
m_pPath[nl.m_nFNode].m_nPreNode = nNode;
}
}
// 开始处理
int nMinNode;
double dDist, dMinDist;
for ( i = 0; i < nNodeNum; i++ )
{
// (2) 在未处理结点中找出距离值最小的结点
nMinNode = -1;
dMinDist = 1.7e+308;
for ( j = 0; j < nNodeNum; j++ )
{
// 让过自身
if ( j == nNode )
continue;
// 让过不连通结点
if ( m_pPath[j].m_dLength < 0 ) // <0 表示无穷大
continue;
// 让过处理过的结点
if ( pMark[j] == 1 )
continue;
// 在未处理过的结点中找出距离最小的
if ( m_pPath[j].m_dLength < dMinDist )
{
dMinDist = m_pPath[j].m_dLength;
nMinNode = j;
}
}
// 如果没找到, 则表示与其他点不连通
if ( nMinNode == -1 )
{
if(pMark)
{
delete pMark;
pMark = NULL;
}
return true;
}
// 处理该距离最小的点
pMark[nMinNode] = 1;
// (3) 调整余下的结点的最短路径
for ( j = 0; j < nNodeNum; j++ )
{
// 让过自身
if ( j == nNode )
continue;
// 让过处理过的结点
if ( pMark[j] == 1 )
continue;
// 调整未处理过的结点的最短路径
// 计算直接相连的结点间的距离
dDist = GetConnectedDistance( nMinNode, j, bWeight );
if ( dDist < 0 ) // 不连通
continue;
// 更新未处理过的结点的最短路径
if ( m_pPath[j].m_dLength < 0 ||
m_pPath[j].m_dLength > m_pPath[nMinNode].m_dLength + dDist )
{
m_pPath[j].m_dLength = m_pPath[nMinNode].m_dLength + dDist ;
m_pPath[j].m_nPreNode = nMinNode;
}
}
}
if(pMark)
{
delete pMark;
pMark = NULL;
}
return true;
}
//-----------------------------------------------------------------------------------------
double CNetLayer::GetConnectedDistance(int nNode1, int nNode2, BOOL bWeight )
{
if ( nNode1 < 0 || nNode1 >= m_arrNodes.GetCount())
return -1;
if ( nNode2 < 0 || nNode2 >= m_arrNodes.GetCount())
return -1;
if ( nNode1 == nNode2 )
return 0;
int nLink;
double dDistance;
double dMinDist = 1.7e+308;
int nRes = 0;
int i = 0;
//遍历与结点1相连的弧段, 判断弧段的另一端的结点是否为结点2, 是则返回距离
NetNode* nd = &(m_arrNodes.GetAt(m_arrNodes.FindIndex(nNode1)));
for ( i = 0; i<nd->m_arrLinks.GetCount(); i++ )
{
NetEdge ng = nd->m_arrLinks.GetAt(nd->m_arrLinks.FindIndex(i));
nLink = ng.nLink;
NetLink nl = m_arrLinks.GetAt(m_arrLinks.FindIndex(nLink));
if(nl.m_nFNode == nNode1 )
{
if(nl.m_nTNode == nNode2 )
{
dDistance = bWeight ? nl.m_fFromImp : nl.m_fLength;
if ( dDistance < dMinDist )
{
dMinDist = dDistance;
nRes = 1;
}
}
}
else if(nl.m_nTNode == nNode1 )
{
if(nl.m_nFNode == nNode2 )
{
dDistance = bWeight ? nl.m_fToImp : nl.m_fLength;
if ( dDistance < dMinDist )
{
dMinDist = dDistance;
nRes = -1;
}
}
}
}
if ( nRes == 0 )
return -1;
return dMinDist;
}
//-----------------------------------------------------------------------------------------
BOOL CNetLayer::CreateResultPath(CList<int, int&>* pNodes, NetLine* line, BOOL bWeight )
{
int i, j;
// 将分析结果结点集转换为线加入到结果图层中
int nNum;
int nRes;
int nNode1, nNode2, nLink;
double dDistance, dRatio;
double dTotalImp;
nNum = pNodes->GetCount();
int idLine;
dTotalImp = 0;
for (i=0; i<nNum-1; i++ )
{
// 得到连接两个结点的最短弧段
nNode1 = pNodes->GetAt(pNodes->FindIndex(i));
nNode2 = pNodes->GetAt(pNodes->FindIndex(i+1));
nRes = IsConnectedDirectly(nNode1, nNode2, &nLink, &dDistance, bWeight );
// 不连通则返回false. 这种情况理论上是不可能出现的.
if ( nRes == 0 )
{
return FALSE;
}
if ( nLink == -1 )
continue;
// 将该弧段的结点按路径顺序加入到结果图层的线中去
NetLink nl = m_arrLinks.GetAt(m_arrLinks.FindIndex(nLink));
idLine = nl.m_GeoID;
NetLine tmpLine(m_layer);
tmpLine.GetLineData( idLine );
// 只加入起始结点和终止结点之间的点
double dDist;
int nSegIndex1, nSegIndex2;
NetPoint ptNearst1, ptNearst2, ptTemp;
NetNode* node1 = &(m_arrNodes.GetAt(m_arrNodes.FindIndex(nNode1)));
NetNode* node2 = &(m_arrNodes.GetAt(m_arrNodes.FindIndex(nNode2)));
ptTemp.x= node1->x;
ptTemp.y= node1->y;
tmpLine.GetNearestPoint(ptTemp, &ptNearst1, &nSegIndex1, &dDist );
ptTemp.x= node2->x;
ptTemp.y= node2->y;
tmpLine.GetNearestPoint(ptTemp, &ptNearst2, &nSegIndex2, &dDist );
dRatio = nl.m_fLength / tmpLine.CalcLength();
if ( nRes == 1 )
{
// 正向
line->m_pCoords.AddTail( ptNearst1 );
for(j=nSegIndex1; j<nSegIndex2; j++ )
line->m_pCoords.AddTail(tmpLine.m_pCoords.GetAt(tmpLine.m_pCoords.FindIndex(j+1)));
line->m_pCoords.AddTail(ptNearst2 );
dTotalImp += nl.m_fFromImp;
}
else if ( nRes == -1 )
{
// 逆向
line->m_pCoords.AddTail( ptNearst1 );
for ( j = nSegIndex1; j > nSegIndex2; j-- )
line->m_pCoords.AddTail(tmpLine.m_pCoords.GetAt(tmpLine.m_pCoords.FindIndex(j)));
line->m_pCoords.AddTail(ptNearst2 );
dTotalImp += nl.m_fToImp;
}
if ( line->m_pCoords.GetCount() < 2 )
{
line->m_pCoords.RemoveAll();
continue;
}
}
return TRUE;
}
//-----------------------------------------------------------------------------------------
int CNetLayer::IsConnectedDirectly(int nNode1, int nNode2, int* nLink,
double* dDistance, BOOL bWeight)
{
*nLink = -1;
*dDistance = 0;
if ( nNode1 < 0 || nNode1 >= m_arrNodes.GetCount())
return 0;
if ( nNode2 < 0 || nNode2 >= m_arrNodes.GetCount())
return 0;
if ( nNode1 == nNode2 )
return 1;
int i = 0;
int nRes = 0;
int nMinLink = -1;
double dMinDist = 1.7e+308;
// 遍历与结点1相连的弧段, 判断弧段的另一端的结点是否为结点2
NetNode* nd = &(m_arrNodes.GetAt(m_arrNodes.FindIndex(nNode1)));
for ( i = 0; i < nd->m_arrLinks.GetCount(); i++ )
{
NetEdge ng = nd->m_arrLinks.GetAt(nd->m_arrLinks.FindIndex(i));
*nLink = ng.nLink;
NetLink nl = m_arrLinks.GetAt(m_arrLinks.FindIndex(*nLink));
if (nl.m_nFNode == nNode1 )
{
if(nl.m_nTNode == nNode2 )
{
*dDistance = bWeight ? nl.m_fFromImp : nl.m_fLength;
if(*dDistance < dMinDist)
{
dMinDist = *dDistance;
nMinLink = *nLink;
nRes = 1;
}
}
}
else if(nl.m_nTNode == nNode1 )
{
if(nl.m_nFNode == nNode2 )
{
*dDistance = bWeight ? nl.m_fToImp : nl.m_fLength;
if(*dDistance < dMinDist)
{
dMinDist = *dDistance;
nMinLink = *nLink;
nRes = -1;
}
}
}
}
if ( nRes == 0 )
{
*nLink = -1;
*dDistance = -1;
return 0;
}
*nLink = nMinLink;
*dDistance = dMinDist;
return nRes;
}
//-----------------------------------------------------------------------------------------
BOOL CNetLayer::UnloadStops()
{
int i, j;
int nLink, nNode;
double dAngle;
// 利用备份数据, 恢复弧段表和结点表, 并清除备份数据
int nCount = m_arrLinkBackups.GetCount();
for(i=0; i<nCount; i++ )
{
NetLinkBackup* nlBK = &(m_arrLinkBackups.GetAt(m_arrLinkBackups.FindIndex(i)));
nLink = nlBK->m_nIndex;
// 恢复弧段表
m_arrLinks.GetAt(m_arrLinks.FindIndex(nLink)).Copy(nlBK->m_Link );
// 恢复点表
nNode = m_arrLinks.GetAt(m_arrLinks.FindIndex(nLink)).m_nTNode;
NetNode* nd = &(m_arrNodes.GetAt(m_arrNodes.FindIndex(nNode)));
dAngle = nd->GetLinkAngle( nLink );
for ( j = nd->m_arrLinks.GetCount() - 1; j>=0 ; j-- )
{
if(nd->m_arrLinks.GetAt(nd->m_arrLinks.FindIndex(j)).nLink >= m_nLinkNum )
{
nd->m_arrLinks.RemoveAt(nd->m_arrLinks.FindIndex(j));
}
}
nd->Add( nLink, dAngle );
}
m_arrLinkBackups.RemoveAll();
if(m_pPath)
{
delete m_pPath;
m_pPath = NULL;
}
return TRUE;
}
//-----------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -