📄 netlayer.cpp
字号:
#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 + -