📄 利用vc+mo最短路径算法--gis开发.htm
字号:
弧段ID(GeoID)<BR> int
m_nFNode; //
起始结点(数组下标索引)<BR> int
m_nTNode; //
终止结点(数组下标索引)<BR> double m_fLength; //
长度<BR> double m_fFromImp; // 正向阻力(阻力系数*长度 或
(1+阻力系数)*长度)<BR> double m_fToImp; //
逆向阻力</P>
<P>public:<BR> NetLink();<BR> void Copy( NetLink link
); // 拷贝操作<BR> BOOL IsEqual( NetLink link );
//
判断是否相等<BR>};<BR>//-----------------------------------------------------------------------------------------<BR>//
用于分裂操作的结构<BR>struct
NetLinkSeg<BR>{<BR> int
nSegID; // 分裂点后面的部分的弧段索引(数组下标索引)<BR> double
dRatio; //
分裂点前面的到起始结点部分的比例<BR>};<BR>//-----------------------------------------------------------------------------------------<BR>//
用于备份弧段的类<BR>class
NetLinkBackup<BR>{<BR>public:<BR> int m_nIndex; //
弧段的索引<BR> NetLink m_Link; //
备份的弧段对象<BR> CList<NetLinkSeg, NetLinkSeg&> m_arrSegs;
// 该弧段被多次分割的比例列表</P>
<P>public:<BR> NetLinkBackup()<BR> {<BR> m_nIndex
= -1;<BR> }</P>
<P> void operator=(const NetLinkBackup& netLink)
<BR> {<BR> m_nIndex =
netLink.m_nIndex;<BR> m_Link =
netLink.m_Link;<BR> for(int i=0;
i<netLink.m_arrSegs.GetCount();
i++)<BR> {<BR> NetLinkSeg nLS =
netLink.m_arrSegs.GetAt(<BR>
netLink.m_arrSegs.FindIndex(i));<BR> m_arrSegs.AddTail(nLS);<BR> }<BR> }</P>
<P> BOOL Add( int nSeg, double dRatio
);<BR>};<BR>//-----------------------------------------------------------------------------------------<BR>//
定义网络上的一条路径<BR>class
NetPath<BR>{<BR>public:<BR> double m_dLength; //
该点到给定点的最短路径长度, -1表示不连通<BR> int m_nPreNode; //
该点在该路径上的前趋结点<BR>public:<BR> NetPath()<BR> {<BR> m_dLength
= -1;<BR> m_nPreNode =
-1;<BR> }<BR>};<BR>//-----------------------------------------------------------------------------------------<BR>class
CNetLayer<BR>{<BR>private:<BR> CList<NetLink,
NetLink&> m_arrLinks; // 弧段表<BR> CList<NetNode,
NetNode&> m_arrNodes; //
节点表<BR> CList<NetLinkBackup, NetLinkBackup&>
m_arrLinkBackups; // 弧段备份表<BR>
<BR> int m_nLinkNum; // 原始弧段数目(网络拓扑建立完成后)
<BR> int m_nNodeNum; // 原始结点数目(网络拓扑建立完成后)
<BR> NetPath* m_pPath; //
某一个点到所有点的最短路径<BR> CMoMapLayer m_layer;
// 图层对象<BR>public:<BR> CNetLayer(CMoMapLayer
layer);<BR> ~CNetLayer(void);</P>
<P> BOOL ReadNetTable();<BR> BOOL PathAnalysis(double x1,
double y1, double x2, double y2, CList<double, double&>*
path );<BR> BOOL LoadStops(CList<NetPoint,
NetPoint&>* pPoints, CList<int, int&>*
pNodes);<BR> BOOL UpdateLinkNodeTable( int nLineID, NetPoint
ptNearest, double dRatio, int* nNewNode );<BR> int GetNode(int
nLineID, int* nFNode, int* nTNode );<BR> double Path(int
nBeginNode, int nEndNode, CList<int, int&>* pNodes, BOOL
bWeight);<BR> BOOL CalcPath( int nNode, int nEndNode , BOOL
bWeight );<BR> double GetConnectedDistance( int nNode1, int
nNode2, BOOL bWeight );<BR> BOOL CreateResultPath(CList<int,
int&>* pNodes, NetLine* line, BOOL bWeight);<BR> int
IsConnectedDirectly(int nNode1, int nNode2, int* nLink, double*
dDistance, BOOL bWeight);<BR> BOOL UnloadStops();<BR>};<BR></P>
<P>//***************************************************************************//</P>
<P>//netlayer.cpp文件</P>
<P>#i nclude "StdAfx.h"<BR>#i nclude "netlayer.h"<BR>#i nclude
"MoRecordset.h"<BR>#i nclude <math.h><BR>#i nclude
"MoLine.h"<BR>#i nclude "MoField.h"<BR>#i nclude "MoFields.h"<BR>#i
nclude "MoPoints.h"<BR>#i nclude "MoPoint.h"<BR>#i nclude
"MoParts.h"<BR>#i nclude "MainFrm.h"<BR>#i nclude "AppApi.h"</P>
<P>//-----------------------------------------------------------------------------------------<BR>NetLine::NetLine(CMoMapLayer
layer)<BR>{<BR> m_layer =
layer;<BR>}<BR>//-----------------------------------------------------------------------------------------<BR>NetLine::~NetLine()<BR>{<BR> m_pCoords.RemoveAll();<BR>}<BR>//-----------------------------------------------------------------------------------------<BR>//
计算线的几何长度<BR>double
NetLine::CalcLength()<BR>{<BR> double dLength = 0.0
; // 保存计算出的线几何长度的结果<BR> int loop
; // 保存循环计数<BR>
<BR> // 检查线的有效性<BR> if ( m_pCoords.GetCount() < 2
)<BR> return 0.0 ;<BR> //
计算线的几何长度<BR> double dist = 0.0 ;<BR> for ( loop = 1 ;
loop<m_pCoords.GetCount(); loop ++
)<BR> {<BR> NetPoint PrePoint =
(NetPoint)m_pCoords.GetAt(m_pCoords.FindIndex(loop
-1));<BR> NetPoint CurPoint =
(NetPoint)m_pCoords.GetAt(m_pCoords.FindIndex(loop));<BR> dist
= sqrt( (PrePoint.x - CurPoint.x) * (PrePoint.x - CurPoint.x)
+<BR>
(PrePoint.y - CurPoint.y) * (PrePoint.y - CurPoint.y))
;<BR> dLength += dist
;<BR> }<BR> <BR> return dLength
;<BR>}<BR>//-----------------------------------------------------------------------------------------<BR>//
通过线的id得到线数据<BR>BOOL NetLine::GetLineData(int id)<BR>{<BR> char
buf[20];<BR> itoa(id, buf, 10);<BR> CMoRecordset
rs;<BR> rs = m_layer.SearchExpression("GeoID = " +
CString(buf));<BR> <BR> if
(!rs)<BR> return FALSE;<BR>
<BR> rs.MoveFirst(); <BR> if
(rs.GetEof())<BR> return FALSE;<BR>
<BR> CMoLine
line(rs.GetFields().Item(COleVariant("shape")).GetValue().pdispVal);<BR> CMoPoints
pts = line.GetParts().Item(COleVariant(long(0),
VT_I4));<BR> m_pCoords.RemoveAll();<BR>
<BR> for (long i = 0; i<pts.GetCount(); i
++)<BR> {<BR> NetPoint pt;<BR> CMoPoint
moPt(pts.Item(COleVariant(i, VT_I4)));<BR> pt.x =
moPt.GetX();<BR> pt.y =
moPt.GetY();<BR> m_pCoords.AddTail(pt);
<BR> }<BR> <BR> return
true;<BR>}<BR>//-----------------------------------------------------------------------------------------<BR>//
得到距离某点最近的线段,返回该线段的id<BR>int NetLine::GetNearestLineData( double x,
double y)<BR>{<BR> CMoRecordset rs =
m_layer.GetRecords();<BR> CMoPoint
pt;<BR> pt.CreateDispatch(_T("MapObjects2.Point"));<BR> pt.SetX(x);<BR> pt.SetY(y);</P>
<P> double dDist = 9999999;<BR> int id =
-1;<BR> <BR> rs.MoveFirst();
<BR> while(!rs.GetEof())<BR> {<BR> CMoFields
fields(rs.GetFields());<BR> CMoField
shapeField(fields.Item(COleVariant("shape")));<BR> CMoLine
line(shapeField.GetValue().pdispVal);<BR> double d =
line.DistanceTo(pt);
<BR>
<BR> if (dDist >
d)<BR> {<BR> dDist =
d;<BR> CString szValue =
fields.Item(COleVariant("Geoid")).GetValueAsString();<BR> id
= atoi(szValue);<BR> }<BR> rs.MoveNext();
<BR> }<BR> <BR> if (id !=
-1)<BR> {<BR> if
(!GetLineData(id))<BR> return
-1;<BR> }<BR> return
id;<BR>}<BR>//-----------------------------------------------------------------------------------------<BR>//
判断两点是否重合<BR>BOOL NetLine::IsPtCoincide( NetPoint ptFirst, NetPoint
ptSecond)<BR>{<BR> if ( fabs(ptFirst.x - ptSecond.x ) <=
0.00000001 <BR> && fabs(ptFirst.y - ptSecond.y )
<= 0.00000001 )<BR> return TRUE;<BR> return
FALSE;<BR>}<BR>//-----------------------------------------------------------------------------------------<BR>//
得到最邻近的点<BR>void NetLine::GetNearestPoint(NetPoint ptP, NetPoint ptA,
NetPoint ptB, <BR>
NetPoint* ptNearest, double* dDistance )<BR>{<BR> double
Px,Py,Ax,Ay,Bx,By;<BR> double AB2,PA2,PB2,AB,PA,PB,S,AREA
;<BR> double med,med1,k1,k2,b1,b2 ;<BR>
<BR> *dDistance = 0;<BR> <BR> if (
IsPtCoincide(ptA,ptB) )<BR> {<BR> ptNearest->x =
ptA.x;<BR> ptNearest->y = ptA.y;<BR> return
;<BR> }<BR> <BR> Px = ptP.x
;<BR> Py = ptP.y ;<BR> Ax = ptA.x ;<BR> Ay = ptA.y
;<BR> Bx = ptB.x ;<BR> By = ptB.y ;<BR> AB2 = (Ax -
Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) ;<BR> PB2 = (Px - Bx) *
(Px - Bx) + (Py - By) * (Py - By) ;<BR> PA2 = (Ax - Px) * (Ax -
Px) + (Ay - Py) * (Ay - Py) ; </P>
<P> if(PA2 + AB2 < PB2 || AB2 + PB2 <
PA2) <BR> {
<BR> if(PA2 >
PB2)<BR> {<BR> med = PB2
;<BR> ptNearest->x = Bx
;<BR> ptNearest->y = By
;<BR> }<BR> else<BR> {<BR> med
= PA2 ;<BR> ptNearest->x = Ax
;<BR> ptNearest->y = Ay
;<BR> }<BR> med = sqrt(med)
; <BR> *dDistance = med ;<BR> return
;<BR> }<BR> <BR> if (PA2 < 0.00000001
|| PB2 < 0.00000001)<BR> {<BR> if(PA2 <
0.00000001)<BR> {<BR> med = sqrt(PA2)
;<BR> *dDistance = med
;<BR> ptNearest->x = Ax
;<BR> ptNearest->y = Ay
;<BR> return ;<BR> }<BR> else
<BR> {<BR> med = sqrt(PB2)
;<BR> *dDistance = med
;<BR> ptNearest->x = Bx
;<BR> ptNearest->y = By
;<BR> return
;<BR> }<BR> }<BR> <BR> AB =
sqrt(AB2) ;<BR> PA = sqrt(PA2) ;<BR> PB = sqrt(PB2)
;<BR> S = (AB + PA + PB) / 2.0 ;<BR> AREA = S
;<BR> AREA *= (S - PA) ;<BR> AREA *= (S - PB)
;<BR> AREA *= (S - AB) ;<BR> AREA = sqrt(AREA)
;<BR> med = (2.0 * AREA) / AB ;<BR> *dDistance = med
;<BR> <BR> med = Ay - By ;<BR> med1 = Ax
- Bx ;<BR> if(fabs(med) < 0.00000001 || fabs(med1) <
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -