⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netlayer.cpp

📁 程序编写环境为Visual Studio.NET 2002
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -