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

📄 netlayer.cpp

📁 程序编写环境为Visual Studio.NET 2002
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "StdAfx.h"
#include "netlayer.h"
#include "MoRecordset.h"
#include <math.h>
#include "MoLine.h"
#include "MoField.h"
#include "MoFields.h"
#include "MoPoints.h"
#include "MoPoint.h"
#include "MoParts.h"
#include "MainFrm.h"
#include "AppApi.h"

//-----------------------------------------------------------------------------------------
NetLine::NetLine(CMoMapLayer layer)
{
	m_layer = layer;
}
//-----------------------------------------------------------------------------------------
NetLine::~NetLine()
{
	m_pCoords.RemoveAll();
}
//-----------------------------------------------------------------------------------------
// 计算线的几何长度
double NetLine::CalcLength()
{
	double	dLength = 0.0 ;		// 保存计算出的线几何长度的结果
	int		loop ;				// 保存循环计数
    
	// 检查线的有效性
	if ( m_pCoords.GetCount() < 2 )
		return 0.0 ;
	// 计算线的几何长度
	double	dist = 0.0 ;
	for ( loop = 1 ; loop<m_pCoords.GetCount(); loop ++ )
	{
		NetPoint PrePoint = (NetPoint)m_pCoords.GetAt(m_pCoords.FindIndex(loop -1));
		NetPoint CurPoint = (NetPoint)m_pCoords.GetAt(m_pCoords.FindIndex(loop));
		dist = sqrt( (PrePoint.x - CurPoint.x) * (PrePoint.x - CurPoint.x) +
			         (PrePoint.y - CurPoint.y) * (PrePoint.y - CurPoint.y)) ;
		dLength += dist ;
	}
	
	return dLength ;
}
//-----------------------------------------------------------------------------------------
// 通过线的id得到线数据
BOOL NetLine::GetLineData(int id)
{
	char buf[20];
	itoa(id, buf, 10);
	CMoRecordset rs;
	rs = m_layer.SearchExpression("GeoID = " + CString(buf));
    
	if (!rs)
		return FALSE;
    
	rs.MoveFirst(); 
	if (rs.GetEof())
		return FALSE;
    
	CMoLine line(rs.GetFields().Item(COleVariant("shape")).GetValue().pdispVal);
	CMoPoints pts = line.GetParts().Item(COleVariant(long(0), VT_I4));
	m_pCoords.RemoveAll();
    
	for (long i = 0; i<pts.GetCount(); i ++)
	{
		NetPoint pt;
		CMoPoint moPt(pts.Item(COleVariant(i, VT_I4)));
		pt.x = moPt.GetX();
		pt.y = moPt.GetY();
		m_pCoords.AddTail(pt); 
	}
    
	return true;
}
//-----------------------------------------------------------------------------------------
// 得到距离某点最近的线段,返回该线段的id
int NetLine::GetNearestLineData( double x, double y)
{
	CMoRecordset rs = m_layer.GetRecords();
	CMoPoint pt;
	pt.CreateDispatch(_T("MapObjects2.Point"));
	pt.SetX(x);
	pt.SetY(y);

	double	dDist = 9999999;
	int		id = -1;
    
	rs.MoveFirst(); 
	while(!rs.GetEof())
	{
		CMoFields fields(rs.GetFields());
		CMoField shapeField(fields.Item(COleVariant("shape")));
		CMoLine line(shapeField.GetValue().pdispVal);
		double d = line.DistanceTo(pt);   					
        
		if (dDist > d)
		{
			dDist = d;
			CString szValue = fields.Item(COleVariant("Geoid")).GetValueAsString();
			id = atoi(szValue);
		}
		rs.MoveNext(); 
	}
    
	if (id != -1)
	{
		if (!GetLineData(id))
			return -1;
	}
	return id;
}
//-----------------------------------------------------------------------------------------
// 判断两点是否重合
BOOL NetLine::IsPtCoincide( NetPoint ptFirst, NetPoint ptSecond)
{
	if ( fabs(ptFirst.x - ptSecond.x ) <= 0.00000001 
		&& fabs(ptFirst.y - ptSecond.y ) <= 0.00000001 )
		return TRUE;
	return FALSE;
}
//-----------------------------------------------------------------------------------------
// 得到最邻近的点
void NetLine::GetNearestPoint(NetPoint ptP, NetPoint ptA, NetPoint ptB, 
							  NetPoint* ptNearest, double* dDistance )
{
	double Px,Py,Ax,Ay,Bx,By;
	double AB2,PA2,PB2,AB,PA,PB,S,AREA ;
	double med,med1,k1,k2,b1,b2 ;
    
	*dDistance = 0;
    
	if ( IsPtCoincide(ptA,ptB) )
	{
		ptNearest->x = ptA.x;
		ptNearest->y = ptA.y;
		return ;
	}
    
	Px = ptP.x ;
	Py = ptP.y ;
	Ax = ptA.x ;
	Ay = ptA.y ;
	Bx = ptB.x ;
	By = ptB.y ;
	AB2 = (Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) ;
	PB2 = (Px - Bx) * (Px - Bx) + (Py - By) * (Py - By) ;
	PA2 = (Ax - Px) * (Ax - Px) + (Ay - Py) * (Ay - Py) ;	

	if(PA2 + AB2 < PB2 || AB2 + PB2 < PA2)	
	{                       
		if(PA2 > PB2)
		{
			med = PB2 ;
			ptNearest->x = Bx ;
			ptNearest->y = By ;
		}
		else
		{
			med = PA2 ;
			ptNearest->x = Ax ;
			ptNearest->y = Ay ;
		}
		med = sqrt(med) ;	
		*dDistance = med ;
		return ;
	}
    
	if (PA2 < 0.00000001 || PB2 < 0.00000001)
	{
		if(PA2 < 0.00000001)
		{
			med = sqrt(PA2) ;
			*dDistance = med ;
			ptNearest->x = Ax ;
			ptNearest->y = Ay ;
			return ;
		}
		else 
		{
			med = sqrt(PB2) ;
			*dDistance = med ;
			ptNearest->x = Bx ;
			ptNearest->y = By ;
			return ;
		}
	}
    
	AB = sqrt(AB2) ;
	PA = sqrt(PA2) ;
	PB = sqrt(PB2) ;
	S = (AB + PA + PB) / 2.0 ;
	AREA = S ;
	AREA *= (S - PA) ;
	AREA *= (S - PB) ;
	AREA *= (S - AB) ;
	AREA = sqrt(AREA) ;
	med = (2.0 * AREA) / AB ;
	*dDistance = med ;
    
	med = Ay - By ;
	med1 = Ax - Bx ;
	if(fabs(med) < 0.00000001 || fabs(med1) < 0.00000001)		
	{	
		if(fabs(med) < 0.00000001)
		{
			ptNearest->x = Px ;
			ptNearest->y = Ay ;
		}
		else
		{
			ptNearest->y = Py ;
			ptNearest->x = Ax ;
		}
	}
	else
	{	
		k1 = (Ay - By) / ( Ax - Bx) ;	
		k2 = -1.0 / k1 ;			
		b1 = Ay - k1 * Ax ;
		b2 = Py - k2 * Px ;
		S = (b2 - b1) / (k1 - k2) ;
		ptNearest->x = S ;
		S = k1 * S + b1 ;
		ptNearest->y = S ;
	}
}
//-----------------------------------------------------------------------------------------
// 得到最邻近的点
void NetLine::GetNearestPoint(NetPoint point, NetPoint* ptNearestPoint, 
							  int* nSegmentIndex, double* dLeastDistance)
{
	int nPointNum = m_pCoords.GetCount();			
	double dDistance;
	NetPoint ptTemp;
    
	NetPoint firstPt = m_pCoords.GetAt(m_pCoords.FindIndex(0));
	NetPoint secondPt = m_pCoords.GetAt(m_pCoords.FindIndex(1));
	GetNearestPoint( point, firstPt, secondPt, ptNearestPoint, dLeastDistance);
	nSegmentIndex = 0 ;
	
	// 遍历每一条弧段来搜索最近的点
	int nIndex ;
	for(nIndex = 1 ; nIndex<nPointNum-1 ; nIndex ++ ) 
	{		
		// 得到最近的点
		GetNearestPoint(point, m_pCoords.GetAt(m_pCoords.FindIndex(0)), 
			m_pCoords.GetAt(m_pCoords.FindIndex(1)), &ptTemp, &dDistance ) ;
        
		// 比较最小的距离
		if( dDistance < *dLeastDistance )
		{
			*dLeastDistance = dDistance ;
			ptNearestPoint->x = ptTemp.x; 
			ptNearestPoint->y = ptTemp.y;
			*nSegmentIndex = nIndex ;
		}
	}
}
//-----------------------------------------------------------------------------------------
// 获得根据给定点分裂线得到的两个部分的比例, 但并不真正分裂线
// 参数point: 给定点
// 参数ptNearestPoint: 分裂线时的分裂点 (返回)
// 参数dRatio: 起始结点部分的比例 (返回)
BOOL NetLine::GetSplitRatioByNearestPoint(NetPoint point, NetPoint* ptNearest, 
										  double* dRatio)
{
	int nIndex = 0;
	double dDistance = 0.0;
    
	int nPointNum = m_pCoords.GetCount();
	// 首先得到最近的点和线段索引
	GetNearestPoint(point, ptNearest, &nIndex, &dDistance );
	
	// 检查线上最近的点是否与首尾点相重合
	if( nIndex == 0 )
	{
		if( IsPtCoincide(*ptNearest, m_pCoords.GetAt(m_pCoords.FindIndex(0))))
		{
			dRatio = 0;
			return true;
		}
	}

	if( nIndex == nPointNum-2 )
	{
		if( IsPtCoincide(*ptNearest, m_pCoords.GetAt(
			             m_pCoords.FindIndex(nPointNum-1))))
		{
			*dRatio = 1.0;
			return true;
		}
	}
    
	// 计算分裂出来的第二条线的长度
	int nLoop;
	double dLength = 0;
	// 如果最近点与本线上的下一点不重合,则需将最近点计算在内
	if ( !IsPtCoincide(*ptNearest, m_pCoords.GetAt(m_pCoords.FindIndex(nIndex+1))))
	{
		NetPoint PostPoint = m_pCoords.GetAt(m_pCoords.FindIndex(nIndex+1));
		dLength += sqrt( ( PostPoint.x - ptNearest->x ) * ( PostPoint.x - ptNearest->x ) + 
			( PostPoint.y - ptNearest->y ) * ( PostPoint.y - ptNearest->y ));
	}
	
	for( nLoop = nIndex+2; nLoop<nPointNum; nLoop ++ )
	{
		NetPoint CurPoint = m_pCoords.GetAt(m_pCoords.FindIndex(nLoop));
		NetPoint PrePoint = m_pCoords.GetAt(m_pCoords.FindIndex(nLoop-1));
		dLength += sqrt( ( CurPoint.x - PrePoint.x ) * ( CurPoint.x - PrePoint.x ) + 
			             ( PrePoint.y - PrePoint.y ) * ( PrePoint.y - PrePoint.y ));
	}
    
	*dRatio = 1.0 - dLength / CalcLength();
	return true;
}
//-----------------------------------------------------------------------------------------
// 加入一个连接的弧段(调用前需确定弧段是连接在该点上的)
BOOL NetNode::Add(int nLink, double dAngle )
{
	// 结点连接的弧段按角度排序
	int i = 0;
	for(i=0; i<m_arrLinks.GetCount(); i++ )
	{
		if(dAngle < m_arrLinks.GetAt(m_arrLinks.FindIndex(i)).fAngle )
			break;
	}
	
	NetEdge pEdge;
	pEdge.nLink = nLink;
	pEdge.fAngle = (float)dAngle;
	m_arrLinks.InsertBefore(m_arrLinks.FindIndex(i), pEdge );
    
	return true;
}
//-----------------------------------------------------------------------------------------
// 删除一个已连接的弧段
BOOL NetNode::Remove( int nLink )
{
	for(int i=0; i<m_arrLinks.GetCount(); i++ )
	{
		if ( nLink == m_arrLinks.GetAt(m_arrLinks.FindIndex(i)).nLink )
		{
			m_arrLinks.RemoveAt(m_arrLinks.FindIndex(i));
			break;
		}
	}
	return true;
}
//-----------------------------------------------------------------------------------------
// 得到一个连接弧段的角度
double NetNode::GetLinkAngle( int nLink )
{
	for(int i=0; i<m_arrLinks.GetCount(); i++ )
	{
		if ( nLink == m_arrLinks.GetAt(m_arrLinks.FindIndex(i)).nLink )
		{
			return m_arrLinks.GetAt(m_arrLinks.FindIndex(i)).fAngle;
		}
	}
	return -1;
}
//-----------------------------------------------------------------------------------------
// 构造函数
NetLink::NetLink()
{
	m_GeoID = -1;
	m_nFNode = -1;
	m_nTNode = -1;
	m_fLength = 0;
	m_fFromImp = 0;
	m_fToImp = 0;
}
//-----------------------------------------------------------------------------------------
// 拷贝另一弧段的数据
void NetLink::Copy( NetLink link )
{
	m_GeoID = link.m_GeoID;
	m_nFNode = link.m_nFNode;
	m_nTNode = link.m_nTNode;
	m_fLength = link.m_fLength;
	m_fFromImp = link.m_fFromImp;
	m_fToImp = link.m_fToImp;
}
//-----------------------------------------------------------------------------------------
// 判断两弧段是否是同一弧段
BOOL NetLink::IsEqual( NetLink link )
{
	return m_GeoID == link.m_GeoID;
}
//-----------------------------------------------------------------------------------------
BOOL NetLinkBackup::Add(int nSeg, double dRatio)
{
	int i = 0;
	for(i = 0; i<m_arrSegs.GetCount(); i++ )
	{
		if (dRatio < m_arrSegs.GetAt(m_arrSegs.FindIndex(i)).dRatio )
			break;
	}
	
	NetLinkSeg pSeg;
	pSeg.nSegID = nSeg;
	pSeg.dRatio = dRatio;
	m_arrSegs.InsertBefore(m_arrSegs.FindIndex(i), pSeg);
    
	return true;
}
//-----------------------------------------------------------------------------------------
CNetLayer::CNetLayer(CMoMapLayer layer)
{
	m_nLinkNum = 0;
	m_nNodeNum = 0;
	m_pPath = NULL;
	m_layer = layer;
}
//-----------------------------------------------------------------------------------------
CNetLayer::~CNetLayer(void)
{
	if(m_pPath)
	{
		delete m_pPath;
		m_pPath = NULL;
	}
}
//-----------------------------------------------------------------------------------------
BOOL CNetLayer::ReadNetTable()
{
	CMainFrame* pMainWnd = (CMainFrame*)AfxGetMainWnd();
	CDaoDatabase* tmpDB = new CDaoDatabase;
	try
	{
		tmpDB->Open(pMainWnd->m_environment.m_szDBName);
	}
	catch (CDaoException* e)
	{
		DisplayDaoException(e);
		delete tmpDB;
		e->Delete();
		return FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -