NetLayer.cs
上传用户:xum6868
上传日期:2009-12-02
资源大小:102k
文件大小:37k
源码类别:

GIS编程

开发平台:

C#

  1. using System;
  2. using System.Collections;
  3. namespace MainSystem
  4. {
  5. public class NetPoint
  6. {
  7. public double x;
  8. public double y;
  9. public NetPoint()
  10. {
  11. x = 0;
  12. y = 0;
  13. }
  14. public NetPoint( double x, double y )
  15. {
  16. this.x = x;
  17. this.y = y;
  18. }
  19. }
  20. public class NetLine
  21. {
  22. // 属性
  23. public ArrayList m_pCoords = null;
  24. private MapObjects2.MapLayer m_layer = null;
  25. // 构造函数
  26. public NetLine(MapObjects2.MapLayer layer)
  27. {
  28. m_pCoords = new ArrayList();
  29. m_layer = layer;
  30. }
  31. // 计算线的几何长度
  32. public double CalcLength()
  33. {
  34. double dLength = 0.0 ; // 保存计算出的线几何长度的结果
  35. int loop ; // 保存循环计数
  36. // 检查线的有效性
  37. if ( m_pCoords.Count < 2 )
  38. return 0.0 ;
  39. // 计算线的几何长度
  40. double dist = 0.0 ;
  41. for ( loop = 1 ; loop < m_pCoords.Count ; loop ++ )
  42. {
  43. dist = Math.Sqrt ( ( ((NetPoint)m_pCoords[loop -1]).x - ((NetPoint)m_pCoords[loop]).x ) * 
  44. ( ((NetPoint)m_pCoords[loop -1]).x - ((NetPoint)m_pCoords[loop]).x ) + 
  45. ( ((NetPoint)m_pCoords[loop -1]).y - ((NetPoint)m_pCoords[loop]).y ) * 
  46. ( ((NetPoint)m_pCoords[loop -1]).y - ((NetPoint)m_pCoords[loop]).y ) ) ;
  47. dLength += dist ;
  48. }
  49. return dLength ;
  50. }
  51. // 通过线的id得到线数据
  52. public bool GetLineData(int id)
  53. {
  54. MapObjects2.Recordset rs;
  55. rs = m_layer.SearchExpression("GeoID = " + id.ToString());
  56. if (null == rs)
  57. return false;
  58. rs.MoveFirst();
  59.  
  60. if (rs.EOF) 
  61. return false;
  62. MapObjects2.Line line = (MapObjects2.Line)rs.Fields.Item("shape").Value;
  63. MapObjects2.Points pts;
  64. pts = (MapObjects2.Points)line.Parts.Item(0);
  65.   
  66. m_pCoords.Clear();
  67.  
  68. for (int i = 0; i < pts.Count; i ++)
  69. {
  70. NetPoint pt = new NetPoint(pts.Item(i).X,pts.Item(i).Y);
  71. m_pCoords.Add(pt); 
  72. }
  73. return true;
  74. }
  75. // 得到距离某点最近的线段,返回该线段的id
  76. public int GetNearestLineData( double x, double y)
  77. {
  78. MapObjects2.Recordset rs = m_layer.Records;
  79. MapObjects2.Point pt = new MapObjects2.PointClass();
  80. pt.X = x;
  81. pt.Y = y;
  82. double dDist = 9999999;
  83. int id = -1;
  84. rs.MoveFirst(); 
  85. while(!rs.EOF)
  86. {
  87. MapObjects2.Line line= (MapObjects2.Line)rs.Fields.Item("shape").Value;
  88. double d = line.DistanceTo(pt);   
  89. if (dDist > d)
  90. {
  91. dDist = d;
  92. string szValue = rs.Fields.Item("Geoid").ValueAsString;
  93. id = Convert.ToInt32(szValue);
  94. }
  95. rs.MoveNext(); 
  96. }
  97. if (id != -1)
  98. {
  99. if (!GetLineData(id))
  100. return -1;
  101. }
  102. return id;
  103. }
  104. public void AddCoord( NetPoint pt )
  105. {
  106. m_pCoords.Add( pt );
  107. }
  108. public bool IsPtCoincide( NetPoint ptFirst, NetPoint ptSecond )
  109. {
  110. if ( Math.Abs(ptFirst.x - ptSecond.x ) <= 0.00000001 && 
  111. Math.Abs(ptFirst.y - ptSecond.y ) <= 0.00000001 )
  112. return true;
  113. return false;
  114. }
  115. public void GetNearestPoint( NetPoint ptP, NetPoint ptA, NetPoint ptB,
  116. out NetPoint ptNearest, out double dDistance )
  117. {
  118. double Px,Py,Ax,Ay,Bx,By ;
  119. double AB2,PA2,PB2,AB,PA,PB,S,AREA ;
  120. double med,med1,k1,k2,b1,b2 ;
  121. ptNearest = new NetPoint();
  122. dDistance = 0;
  123. if ( IsPtCoincide(ptA,ptB) )
  124. {
  125. ptNearest = ptA;
  126. return ;
  127. }
  128. Px = ptP.x ;
  129. Py = ptP.y ;
  130. Ax = ptA.x ;
  131. Ay = ptA.y ;
  132. Bx = ptB.x ;
  133. By = ptB.y ;
  134. AB2 = (Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) ;
  135. PB2 = (Px - Bx) * (Px - Bx) + (Py - By) * (Py - By) ;
  136. PA2 = (Ax - Px) * (Ax - Px) + (Ay - Py) * (Ay - Py) ;
  137. if(PA2 + AB2 < PB2 || AB2 + PB2 < PA2)
  138. {                       
  139. if(PA2>PB2)
  140. {
  141. med = PB2 ;
  142. ptNearest.x = Bx ;
  143. ptNearest.y = By ;
  144. }
  145. else
  146. {
  147. med = PA2 ;
  148. ptNearest.x = Ax ;
  149. ptNearest.y = Ay ;
  150. }
  151. med = Math.Sqrt(med) ;
  152. dDistance = med ;
  153. return ;
  154. }
  155. if (PA2 < 0.00000001 || PB2 < 0.00000001)
  156. {
  157. if(PA2 < 0.00000001)
  158. {
  159. med = Math.Sqrt(PA2) ;
  160. dDistance = med ;
  161. ptNearest.x = Ax ;
  162. ptNearest.y = Ay ;
  163. return ;
  164. }
  165. else 
  166. {
  167. med = Math.Sqrt(PB2) ;
  168. dDistance = med ;
  169. ptNearest.x = Bx ;
  170. ptNearest.y = By ;
  171. return ;
  172. }
  173. }
  174. AB = Math.Sqrt(AB2) ;
  175. PA = Math.Sqrt(PA2) ;
  176. PB = Math.Sqrt(PB2) ;
  177. S = (AB + PA + PB) / 2.0 ;
  178. AREA = S ;
  179. AREA *= (S - PA) ;
  180. AREA *= (S - PB) ;
  181. AREA *= (S - AB) ;
  182. AREA = Math.Sqrt(AREA) ;
  183. med = (2.0 * AREA) / AB ;
  184. dDistance = med ;
  185. med = Ay - By ;
  186. med1 = Ax - Bx ;
  187. if(Math.Abs(med) < 0.00000001 || Math.Abs(med1) < 0.00000001)
  188. {
  189. if(Math.Abs(med) < 0.00000001)
  190. {
  191. ptNearest.x = Px ;
  192. ptNearest.y = Ay ;
  193. }
  194. else
  195. {
  196. ptNearest.y = Py ;
  197. ptNearest.x = Ax ;
  198. }
  199. }
  200. else
  201. {
  202. k1 = (Ay - By) / ( Ax - Bx) ;
  203. k2 = -1.0 / k1 ;
  204. b1 = Ay - k1 * Ax ;
  205. b2 = Py - k2 * Px ;
  206. S = (b2 - b1) / (k1 - k2) ;
  207. ptNearest.x = S ;
  208. S = k1 * S + b1 ;
  209. ptNearest.y = S ;
  210. }
  211. return;
  212. }
  213. public void GetNearestPoint( NetPoint point, out NetPoint ptNearestPoint, 
  214. out int nSegmentIndex,out double dLeastDistance )
  215. {
  216. int nPointNum = m_pCoords.Count;
  217. double dDistance;
  218. NetPoint ptTemp;
  219. GetNearestPoint( point, (NetPoint)m_pCoords[0],(NetPoint)m_pCoords[1],out ptNearestPoint,out dLeastDistance);
  220. nSegmentIndex = 0 ;
  221. //遍历每一条弧段来搜索最近的点
  222. int nIndex ;
  223. for( nIndex = 1 ; nIndex < nPointNum-1 ; nIndex ++ ) 
  224. {
  225. //得到最近的点
  226. GetNearestPoint( point, (NetPoint)m_pCoords[0], (NetPoint)m_pCoords[1], out ptTemp, out dDistance ) ;
  227. //比较最小的距离
  228. if( dDistance < dLeastDistance )
  229. {
  230. dLeastDistance = dDistance ;
  231. ptNearestPoint = ptTemp ; 
  232. nSegmentIndex = nIndex ;
  233. }
  234. }
  235. return ;
  236. }
  237. // 获得根据给定点分裂线得到的两个部分的比例, 但并不真正分裂线
  238. // point: 给定点
  239. // ptNearestPoint: 分裂线时的分裂点 (返回)
  240. // dRatio: 起始结点部分的比例 (返回)
  241. public bool GetSplitRatioByNearestPoint( NetPoint point, out NetPoint ptNearest, out double dRatio )
  242. {
  243. int nIndex;
  244. double dDistance;
  245. int nPointNum = m_pCoords.Count;
  246. //首先得到最近的点和线段索引
  247. GetNearestPoint( point, out ptNearest, out nIndex, out dDistance );
  248. //检查线上最近的点是否与首尾点相重合
  249. if( nIndex == 0 )
  250. {
  251. if( IsPtCoincide( ptNearest, (NetPoint)m_pCoords[0] ) )
  252. {
  253. dRatio = 0;
  254. return true;
  255. }
  256. }
  257. if( nIndex == nPointNum-2 )
  258. {
  259. if( IsPtCoincide( ptNearest, (NetPoint)m_pCoords[nPointNum-1] ))
  260. {
  261. dRatio = 1;
  262. return true;
  263. }
  264. }
  265. //计算分裂出来的第二条线的长度
  266. int nLoop;
  267. double dLength = 0;
  268. //如果最近点与本线上的下一点不重合,则需将最近点计算在内
  269. if ( !IsPtCoincide(ptNearest, (NetPoint)m_pCoords[nIndex+1] ) )
  270. {
  271. dLength += Math.Sqrt( ( ((NetPoint)m_pCoords[nIndex+1]).x - ptNearest.x ) * 
  272. ( ((NetPoint)m_pCoords[nIndex+1]).x - ptNearest.x ) + 
  273. ( ((NetPoint)m_pCoords[nIndex+1]).y - ptNearest.y ) * 
  274. ( ((NetPoint)m_pCoords[nIndex+1]).y - ptNearest.y )
  275. );
  276. }
  277. for( nLoop = nIndex+2 ; nLoop < nPointNum ; nLoop ++ )
  278. {
  279. dLength += Math.Sqrt( ( ((NetPoint)m_pCoords[nLoop]).x - ((NetPoint)m_pCoords[nLoop-1]).x ) * 
  280. ( ((NetPoint)m_pCoords[nLoop]).x - ((NetPoint)m_pCoords[nLoop-1]).x ) + 
  281. ( ((NetPoint)m_pCoords[nLoop]).y - ((NetPoint)m_pCoords[nLoop-1]).y ) * 
  282. ( ((NetPoint)m_pCoords[nLoop]).y - ((NetPoint)m_pCoords[nLoop-1]).y )
  283. );
  284. }
  285. dRatio = 1 - dLength / CalcLength();
  286. return true;
  287. }
  288. }
  289. public class NetEdge
  290. {
  291. public int  nLink; // 连接的弧段索引(数组下标索引)
  292. public float fAngle; // 该弧段的水平夹角
  293. public NetEdge()
  294. {
  295. nLink = -1;
  296. fAngle = 0;
  297. }
  298. };
  299. public class NetNode : NetPoint
  300. {
  301. public ArrayList m_arrLinks = null; // 与该点连接的弧段数组, 弧段按角度排序
  302. public NetNode() 
  303. {
  304. m_arrLinks = new ArrayList();
  305. }
  306. public NetNode( double x, double y ) 
  307. {
  308. this.x = x;
  309. this.y = y;
  310. m_arrLinks = new ArrayList();
  311. }
  312. // 加入一个连接的弧段(调用前需确定弧段是连接在该点上的)
  313. public bool Add( int nLink, double dAngle )
  314. {
  315. // 结点连接的弧段按角度排序
  316. int i = 0;
  317. for (  i = 0; i < m_arrLinks.Count; i++ )
  318. {
  319. if ( dAngle < ((NetEdge)m_arrLinks[i]).fAngle )
  320. break;
  321. }
  322. NetEdge pEdge = new NetEdge();
  323. pEdge.nLink = nLink;
  324. pEdge.fAngle = (float)dAngle;
  325. m_arrLinks.Insert(i, pEdge );
  326. return true;
  327. }
  328. // 删除一个已连接的弧段
  329. public bool Remove( int nLink )
  330. {
  331. for ( int i = 0; i < m_arrLinks.Count ; i++ )
  332. {
  333. if ( nLink == ((NetEdge)m_arrLinks[i]).nLink )
  334. {
  335. m_arrLinks.RemoveAt( i );
  336. break;
  337. }
  338. }
  339. return true;
  340. }
  341. // 得到一个连接弧段的角度
  342. public double GetLinkAngle( int nLink )
  343. {
  344. for ( int i = 0; i < m_arrLinks.Count ; i++ )
  345. {
  346. if ( nLink == ((NetEdge)m_arrLinks[i]).nLink )
  347. {
  348. return ((NetEdge)m_arrLinks[i]).fAngle;
  349. }
  350. }
  351. return -1;
  352. }
  353. }
  354. // 网络弧段(链)类
  355. public class NetLink
  356. {
  357. public int m_GeoID; // 弧段ID(GeoID)
  358. public int m_nFNode; // 起始结点(数组下标索引)
  359. public int m_nTNode; // 终止结点(数组下标索引)
  360. public double m_fLength; // 长度
  361. public double m_fFromImp; // 正向阻力(阻力系数*长度 或 (1+阻力系数)*长度)
  362. public double m_fToImp; // 逆向阻力
  363. public NetLink()
  364. {
  365. m_GeoID = -1;
  366. m_nFNode = -1;
  367. m_nTNode = -1;
  368. m_fLength = 0;
  369. m_fFromImp = 0;
  370. m_fToImp = 0;
  371. }
  372. public void Copy( NetLink link )
  373. {
  374. m_GeoID = link.m_GeoID;
  375. m_nFNode = link.m_nFNode;
  376. m_nTNode = link.m_nTNode;
  377. m_fLength = link.m_fLength;
  378. m_fFromImp = link.m_fFromImp;
  379. m_fToImp = link.m_fToImp;
  380. }
  381. public bool IsEqual( NetLink link )
  382. {
  383. return m_GeoID == link.m_GeoID;
  384. }
  385. }
  386. public class NetLinkSeg
  387. {
  388. public int nSegID; // 分裂点后面的部分的弧段索引(数组下标索引)
  389. public double dRatio; // 分裂点前面的到起始结点部分的比例
  390. };
  391. // 用于备份弧段的类
  392. public class NetLinkBackup
  393. {
  394. public int m_nIndex; // 弧段的索引
  395. public NetLink m_Link=null; // 备份的弧段对象
  396. public ArrayList m_arrSegs; // 该弧段被多次分割的比例列表, 数目=段数-1, 即等于分裂点数
  397. public NetLinkBackup()
  398. {
  399. m_nIndex = -1;
  400. m_Link = new NetLink();
  401. m_arrSegs = new ArrayList();
  402. }
  403. public bool Add( int nSeg, double dRatio )
  404. {
  405. int i = 0;
  406. for ( i = 0; i < m_arrSegs.Count; i++ )
  407. {
  408. if ( dRatio < ((NetLinkSeg)m_arrSegs[i]).dRatio )
  409. break;
  410. }
  411. NetLinkSeg pSeg = new NetLinkSeg();
  412. pSeg.nSegID = nSeg;
  413. pSeg.dRatio = dRatio;
  414. m_arrSegs.Insert( i, pSeg );
  415. return true;
  416. }
  417. }
  418. public class NetPath
  419. {
  420. public double m_dLength; // 该点到给定点的最短路径长度, -1表示无穷大,即不连通
  421. public int m_nPreNode; // 该点在该路径上的前趋结点
  422. public NetPath()
  423. {
  424. m_dLength = -1;
  425. m_nPreNode = -1;
  426. }
  427. }
  428. /// <summary>
  429. /// Summary description for NetLayer.
  430. /// </summary>
  431. public class NetLayer
  432. {
  433. private ArrayList m_arrLinks; // 弧段表
  434. private ArrayList m_arrNodes; // 结点表
  435. private ArrayList m_arrStops; // 站点表
  436. private ArrayList m_arrLinkBackups; // 弧段备份表
  437. private int m_nLinkNum; // 原始弧段数目(网络拓扑建立完成后) 注意: 和m_arrLinks的大小可能是不相等的
  438. private int m_nNodeNum; // 原始结点数目(网络拓扑建立完成后) 注意: 和m_arrNodes的大小可能是不相等的
  439. private NetPath[] m_pPath; // 某一个点到所有点的最短路径. 每个点只记录它在路径上的前趋结点
  440. private MapObjects2.MapLayer m_layer = null;
  441. private System.Data.DataSet m_dataSet = null; 
  442. public NetLayer(MapObjects2.MapLayer layer, System.Data.DataSet dataSet)
  443. {
  444. m_nLinkNum = 0;
  445. m_nNodeNum = 0;
  446. m_pPath = null;
  447. m_dataSet = dataSet;
  448. m_layer = layer;
  449. }
  450. public bool ReadNetTable()
  451. {
  452. m_arrLinks = new ArrayList();
  453. m_arrNodes = new ArrayList();
  454. m_arrStops = new ArrayList();
  455. m_arrLinkBackups = new ArrayList();
  456. System.Data.DataTable Tbl = m_dataSet.Tables["AAT"];
  457. System.Data.DataRow[] rows = Tbl.Select();
  458. foreach (System.Data.DataRow myRow in rows)
  459. {
  460. NetLink lk = new NetLink();
  461. lk.m_GeoID = (int)myRow["GeoID"];
  462. lk.m_nFNode = (int)myRow["FNODE"];
  463. lk.m_nTNode = (int)myRow["TNODE"];
  464. lk.m_fLength = (double)myRow["LENGTH"];
  465. lk.m_fFromImp  = (double)myRow["FIMP"]; 
  466. lk.m_fToImp  = (double)myRow["TIMP"]; 
  467. m_arrLinks.Add( lk );
  468. }
  469. Tbl = m_dataSet.Tables["NAT"];
  470. rows = Tbl.Select();
  471. foreach (System.Data.DataRow myRow in rows)
  472. {
  473. int nNode, nLink;
  474. double x, y, dAngle;
  475. string szArcID, szAngle;
  476. nNode = (int)myRow["NODEID"];
  477. x = (double)myRow["X"];
  478. y = (double)myRow["Y"];
  479. szArcID = myRow["ARCID"].ToString();
  480. szAngle = myRow["ANGLE"].ToString();
  481. NetNode node = new NetNode(x,y);
  482. m_arrNodes.Add( node );
  483. int nPos;
  484. string szTemp;
  485. while ( (nPos = szArcID.IndexOf( ';' )) != -1 )
  486. {
  487. szTemp = szArcID.Substring( 0,nPos );
  488. nLink = Convert.ToInt32( szTemp );
  489. szArcID = szArcID.Substring( nPos+1 );
  490. nPos = szAngle.IndexOf( ';' );
  491. if ( nPos == -1 )
  492. continue;
  493. szTemp = szAngle.Substring(0, nPos );
  494. dAngle = Convert.ToDouble( szTemp );
  495. szAngle = szAngle.Substring( nPos + 1 );
  496. node.Add( nLink, dAngle );
  497. }
  498. }
  499. return true;
  500. }
  501. public bool PathAnalysis( double x1, double y1, double x2, double y2, out ArrayList path )
  502. {
  503. path = new ArrayList();
  504. NetPoint pt1 = new NetPoint( x1, y1 );
  505. NetPoint pt2 = new NetPoint( x2, y2 );
  506. ArrayList points = new ArrayList();
  507. points.Add( pt1 );
  508. points.Add( pt2 );
  509. ArrayList stops = null;
  510. if ( !LoadStops( points, out stops ) )
  511. return false;
  512. if ( stops.Count != 2 )
  513. return false;
  514. ArrayList nodes = null;
  515. double dDistance;
  516. dDistance = Path( (int)stops[0], (int)stops[1], out nodes, false );
  517. if ( dDistance < 0 )
  518. return false;
  519. NetLine line = null;
  520. if ( !CreateResultPath( nodes, out line, false ) )
  521. return false;
  522. for ( int i = 0; i < line.m_pCoords.Count; i++ )
  523. {
  524. path.Add( ((NetPoint)line.m_pCoords[i]).x );
  525. path.Add( ((NetPoint)line.m_pCoords[i]).y );
  526. }
  527. UnloadStops();
  528. return true;
  529. }
  530. // 加入一组坐标作为站点或者中心点, 用于分析. LoadStops与UnloadStops必须一一对应
  531. private bool LoadStops( ArrayList pPoints, out ArrayList pNodes )
  532. {
  533. int nLineID;
  534. int i, nNewNode;
  535. NetPoint ptNearest;
  536. double dRatio;
  537. pNodes = new ArrayList();
  538. // 先清空站点表
  539. m_arrStops.Clear();
  540. int nNum = pPoints.Count;
  541. for ( i = 0; i < nNum; i++ )
  542. {
  543. // 计算距离该点最近的线
  544. NetLine line = new NetLine(m_layer);
  545. nLineID = line.GetNearestLineData( ((NetPoint)pPoints[i]).x, ((NetPoint)pPoints[i]).y);
  546. if ( nLineID == -1 )
  547. {
  548. line = null;
  549. return false;
  550. }
  551. // 计算该点分裂该线的位置, 并不实际分裂该线, 只是计算分裂的比例, 用于更改弧段表和结点表
  552. dRatio = 0;
  553. line.GetSplitRatioByNearestPoint( (NetPoint)pPoints[i], out ptNearest, out dRatio );
  554. // 更新弧段表和结点表
  555. UpdateLinkNodeTable( nLineID, ptNearest, dRatio, out nNewNode );
  556. line = null;
  557. if ( pNodes.Count > 0 )
  558. {
  559. if ( ((int)pNodes[pNodes.Count-1]) == nNewNode )
  560. continue;
  561. }
  562. pNodes.Add( nNewNode );
  563. }
  564. // 填充需要返回的结点数组
  565. if ( pNodes.Count == 0 )
  566. {
  567. pNodes = null;
  568. return false;
  569. }
  570. return true;
  571. }
  572. // 外部结点更新弧段表和结点表
  573. // nNewNode: 加入该点后返回的新结点的标识
  574. private bool UpdateLinkNodeTable( int nLineID, NetPoint ptNearest, double dRatio, out int nNewNode )
  575. {
  576. int i, j;
  577. bool bFound;
  578. double dRatio2;
  579. int nCurLink, nNewLink;
  580. int nCurFNode, nCurTNode;
  581. nNewNode = -1;
  582. // 与某条弧段的首点或者位点重合, 不需要更改弧段表和结点表
  583. if ( Math.Abs(dRatio) < 0.00000001 )
  584. {
  585. // 首点
  586. nCurLink = GetNode( nLineID, out nCurFNode, out nCurTNode );
  587. nNewNode = nCurFNode;
  588. return true;
  589. }
  590. else if ( Math.Abs(1-dRatio) < 0.00000001 )
  591. {
  592. // 尾点
  593. nCurLink = GetNode( nLineID, out nCurFNode, out nCurTNode );
  594. nNewNode = nCurTNode;
  595. return true;
  596. }
  597. bFound = false;
  598. for ( i = 0; i < m_arrLinkBackups.Count; i++ )
  599. {
  600. if ( ((NetLinkBackup)m_arrLinkBackups[i]).m_Link.m_GeoID == nLineID )
  601. {
  602. bFound = true;
  603. break;
  604. }
  605. }
  606. if ( bFound )
  607. {
  608. for ( j = 0; j < ((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs.Count; j++ )
  609. {
  610. // 如果新点与原有的点重合, 则直接返回原来的点
  611. double r = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j]).dRatio;
  612. if ( Math.Abs( r - dRatio) < 0.00000001 )
  613. {
  614. if ( j == 0 )
  615. {
  616. nCurLink = GetNode( nLineID, out nCurFNode, out nCurTNode );
  617. nNewNode = nCurTNode;
  618. return true;
  619. }
  620. else
  621. {
  622. nCurLink = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j-1]).nSegID;
  623. nNewNode = ((NetLink)m_arrLinks[nCurLink]).m_nTNode;
  624. return true;
  625. }
  626. }
  627. // 没有重合的点
  628. r = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j]).dRatio;
  629. if ( dRatio < r )
  630. break;
  631. }
  632. if ( j == 0 )
  633. {
  634. // 第一段
  635. nCurLink = GetNode( nLineID, out nCurFNode, out nCurTNode );
  636. if ( nCurLink == -1 )
  637. return false;
  638. // 更新结点表
  639. nNewLink = m_arrLinks.Count;
  640. NetNode pNode = new NetNode( ptNearest.x, ptNearest.y );
  641. pNode.Add( nNewLink, -1 ); // 这里暂时用-1角度,待修改 Add code here
  642. pNode.Add( nCurLink, -1 );
  643. m_arrNodes.Add( pNode );
  644. ((NetNode)m_arrNodes[nCurTNode]).Remove( nCurLink );
  645. ((NetNode)m_arrNodes[nCurTNode]).Add( nNewLink, -1 );
  646. // 更新弧段表
  647. nNewNode = m_arrNodes.Count - 1;
  648. dRatio2 = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[0]).dRatio;
  649. NetLink pLink = new NetLink();
  650. pLink.m_GeoID = nLineID;
  651. pLink.m_nFNode = nNewNode;
  652. pLink.m_nTNode = ((NetLink)m_arrLinks[((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[0]).nSegID]).m_nFNode;
  653. pLink.m_fLength = (float)(((NetLink)m_arrLinks[nCurLink]).m_fLength * ( dRatio2 - dRatio ));
  654. pLink.m_fFromImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fFromImp * ( dRatio2 - dRatio ));
  655. pLink.m_fToImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fToImp * ( dRatio2 - dRatio ));
  656. m_arrLinks.Add( pLink );
  657. ((NetLink)m_arrLinks[nCurLink]).m_nTNode = nNewNode;
  658. ((NetLink)m_arrLinks[nCurLink]).m_fLength = (float)(((NetLink)m_arrLinks[nCurLink]).m_fLength * dRatio);
  659. ((NetLink)m_arrLinks[nCurLink]).m_fFromImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fFromImp * dRatio);
  660. ((NetLink)m_arrLinks[nCurLink]).m_fToImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fToImp* dRatio);
  661. ((NetLinkBackup)m_arrLinkBackups[i]).Add( nNewLink, dRatio );
  662. }
  663. else if ( j == ((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs.Count )
  664. {
  665. // 最后一段
  666. nCurLink = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j-1]).nSegID;
  667. nCurFNode = ((NetLink)m_arrLinks[nCurLink]).m_nFNode;
  668. nCurTNode = ((NetLink)m_arrLinks[nCurLink]).m_nTNode;
  669. // 更新结点表
  670. nNewLink = m_arrLinks.Count;
  671. NetNode pNode = new NetNode( ptNearest.x, ptNearest.y );
  672. pNode.Add( nNewLink, -1 ); // 这里暂时用-1角度,待修改 Add code here
  673. pNode.Add( nCurLink, -1 );
  674. m_arrNodes.Add( pNode );
  675. double dAngle = ((NetNode)m_arrNodes[nCurTNode]).GetLinkAngle( nCurLink ); // 最后一段保留原角度
  676. ((NetNode)m_arrNodes[nCurTNode]).Remove( nCurLink );
  677. ((NetNode)m_arrNodes[nCurTNode]).Add( nNewLink, dAngle );
  678. // 更新弧段表
  679. nNewNode = m_arrNodes.Count - 1;
  680. NetLink pLink = new NetLink();
  681. pLink.m_GeoID = nLineID;
  682. pLink.m_nFNode = nNewNode;
  683. pLink.m_nTNode = nCurTNode;
  684. pLink.m_fLength = (float)(((NetLink)m_arrLinks[i]).m_fLength * ( 1 - dRatio ));
  685. pLink.m_fFromImp = (float)(((NetLink)m_arrLinks[i]).m_fFromImp * ( 1 - dRatio ));
  686. pLink.m_fToImp = (float)(((NetLink)m_arrLinks[i]).m_fToImp * ( 1 - dRatio ));
  687. m_arrLinks.Add( pLink );
  688. dRatio2 = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j-1]).dRatio;
  689. ((NetLink)m_arrLinks[nCurLink]).m_nTNode = nNewNode;
  690. ((NetLink)m_arrLinks[nCurLink]).m_fLength = (float)(((NetLink)m_arrLinks[nCurLink]).m_fLength * ( dRatio - dRatio2) );
  691. ((NetLink)m_arrLinks[nCurLink]).m_fFromImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fFromImp * ( dRatio - dRatio2) );
  692. ((NetLink)m_arrLinks[nCurLink]).m_fToImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fToImp* ( dRatio - dRatio2) );
  693. ((NetLinkBackup)m_arrLinkBackups[i]).Add( nNewLink, dRatio );
  694. }
  695. else
  696. {
  697. // 中间某一段
  698. nCurLink = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j-1]).nSegID;
  699. nCurFNode = ((NetLink)m_arrLinks[nCurLink]).m_nFNode;
  700. nCurTNode = ((NetLink)m_arrLinks[nCurLink]).m_nTNode;
  701. // 更新结点表
  702. nNewLink = m_arrLinks.Count;
  703. NetNode pNode = new NetNode( ptNearest.x, ptNearest.y );
  704. pNode.Add( nNewLink, -1 ); // 这里暂时用-1角度,待修改 Add code here
  705. pNode.Add( nCurLink, -1 );
  706. m_arrNodes.Add( pNode );
  707. ((NetNode)m_arrNodes[nCurTNode]).Remove( nCurLink );
  708. ((NetNode)m_arrNodes[nCurTNode]).Add( nNewLink, -1 );
  709. // 更新弧段表
  710. nNewNode = m_arrNodes.Count - 1;
  711. dRatio2 = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j]).dRatio;
  712. NetLink pLink = new NetLink();
  713. pLink.m_GeoID = nLineID;
  714. pLink.m_nFNode = nNewNode;
  715. pLink.m_nTNode = nCurTNode;
  716. pLink.m_fLength = (float)(((NetLink)m_arrLinks[i]).m_fLength * ( dRatio2 - dRatio ));
  717. pLink.m_fFromImp = (float)(((NetLink)m_arrLinks[i]).m_fFromImp * ( dRatio2 - dRatio ));
  718. pLink.m_fToImp = (float)(((NetLink)m_arrLinks[i]).m_fToImp * ( dRatio2 - dRatio ));
  719. m_arrLinks.Add( pLink );
  720. dRatio2 = ((NetLinkSeg)((NetLinkBackup)m_arrLinkBackups[i]).m_arrSegs[j-1]).dRatio;
  721. ((NetLink)m_arrLinks[nCurLink]).m_nTNode = nNewNode;
  722. ((NetLink)m_arrLinks[nCurLink]).m_fLength = (float)(((NetLink)m_arrLinks[nCurLink]).m_fLength * ( dRatio - dRatio2) );
  723. ((NetLink)m_arrLinks[nCurLink]).m_fFromImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fFromImp * ( dRatio - dRatio2) );
  724. ((NetLink)m_arrLinks[nCurLink]).m_fToImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fToImp* ( dRatio - dRatio2) );
  725. ((NetLinkBackup)m_arrLinkBackups[i]).Add( nNewLink, dRatio );
  726. }
  727. }
  728. else
  729. {
  730. nCurLink = GetNode( nLineID, out nCurFNode, out nCurTNode );
  731. if ( nCurLink == -1 )
  732. return false;
  733. nNewLink = m_arrLinks.Count;
  734. // 备份
  735. NetLinkBackup pBackup = new NetLinkBackup();
  736. pBackup.m_nIndex = nCurLink;
  737. pBackup.m_Link.Copy((NetLink)m_arrLinks[nCurLink]);
  738. pBackup.Add( nNewLink, dRatio );
  739. m_arrLinkBackups.Add( pBackup );
  740. // 更新结点表
  741. NetNode pNode = new NetNode( ptNearest.x, ptNearest.y );
  742. pNode.Add( nNewLink, -1 ); // 这里暂时用0角度,待修改 Add code here
  743. pNode.Add( nCurLink, -1 );
  744. m_arrNodes.Add( pNode );
  745. double dAngle = ((NetNode)m_arrNodes[nCurTNode]).GetLinkAngle( nCurLink ); // 最后一段保留原角度
  746. ((NetNode)m_arrNodes[((NetLink)m_arrLinks[nCurLink]).m_nTNode]).Remove( nCurLink );
  747. ((NetNode)m_arrNodes[((NetLink)m_arrLinks[nCurLink]).m_nTNode]).Add( nNewLink, dAngle );
  748. // 更新弧段表
  749. nNewNode = m_arrNodes.Count - 1;
  750. NetLink pLink = new NetLink();
  751. pLink.m_GeoID = nLineID;
  752. pLink.m_nFNode = nNewNode;
  753. pLink.m_nTNode = ((NetLink)m_arrLinks[nCurLink]).m_nTNode;
  754. pLink.m_fLength = (float)(((NetLink)m_arrLinks[nCurLink]).m_fLength * ( 1 - dRatio ));
  755. pLink.m_fFromImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fFromImp * ( 1 - dRatio ));
  756. pLink.m_fToImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fToImp * ( 1 - dRatio ));
  757. m_arrLinks.Add( pLink );
  758. ((NetLink)m_arrLinks[nCurLink]).m_nTNode = nNewNode;
  759. ((NetLink)m_arrLinks[nCurLink]).m_fLength = (float)(((NetLink)m_arrLinks[nCurLink]).m_fLength * dRatio);
  760. ((NetLink)m_arrLinks[nCurLink]).m_fFromImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fFromImp * dRatio);
  761. ((NetLink)m_arrLinks[nCurLink]).m_fToImp = (float)(((NetLink)m_arrLinks[nCurLink]).m_fToImp* dRatio);
  762. }
  763. return true;
  764. }
  765. // 得到结点号, 返回弧段索引号(数组下标索引), -1表示失败
  766. private int GetNode( int nLineID, out int nFNode, out int nTNode )
  767. {
  768. nFNode = -1;
  769. nTNode = -1;
  770. for ( int i = 0; i < m_arrLinks.Count; i++ )
  771. {
  772. if ( nLineID == ((NetLink)m_arrLinks[i]).m_GeoID )
  773. {
  774. nFNode = ((NetLink)m_arrLinks[i]).m_nFNode;
  775. nTNode = ((NetLink)m_arrLinks[i]).m_nTNode;
  776. return i;
  777. }
  778. }
  779. return -1;
  780. }
  781. // 计算两点间的最短路径
  782. // 参数含义:  nBeginNode 起始结点
  783. //            nEndNode 终止结点
  784. //            pNodes 路径顺序经过的结点数组, 返回参数
  785. //   bWeight TRUE为计算考虑方向权重最优路径, FALSE为不考虑方向权重的最短路径
  786. // 注意: pNode在函数内部开辟内存, 函数调用者负责在外部删除该内存
  787. // 返回路径总长度,<0 表示没有连通的路径
  788. private double Path( int nBeginNode, int nEndNode, out ArrayList pNodes, bool bWeight )
  789. {
  790. pNodes= null;
  791. if ( nBeginNode < 0 || nBeginNode >= m_arrNodes.Count )
  792. return -1;
  793. if ( nEndNode < 0 || nEndNode >= m_arrNodes.Count )
  794. return -1;
  795. pNodes = new ArrayList();
  796. // 如果两个结点相同
  797. if ( nBeginNode == nEndNode )
  798. {
  799. pNodes.Add( nBeginNode );
  800. return 0;
  801. }
  802. // 计算nBeginNode到其他所有结点的最短路径
  803. if ( !CalcPath( nBeginNode, nEndNode, bWeight ) )
  804. return -1;
  805. // 提取从nBeginNode到nEndNode的路径
  806. // 从nEndNode向前搜索前趋结点
  807. int nNode;
  808. nNode = nEndNode;
  809. while ( true )
  810. {
  811. // 如果没有前趋结点, 不连通
  812. if ( m_pPath[nNode].m_nPreNode == -1 )
  813. return -1;
  814. // 如果前趋结点为起始结点, 路径结束
  815. if ( m_pPath[nNode].m_nPreNode == nBeginNode )
  816. {
  817. pNodes.Add( nNode );
  818. break;
  819. }
  820. // 加入中间结点
  821. pNodes.Add( nNode );
  822. nNode = m_pPath[nNode].m_nPreNode;
  823. }
  824. // 加入起点
  825. pNodes.Add( nBeginNode );
  826. // 因为是从nEndNode到nBeginNode加入的, 所以要作一次倒序
  827. pNodes.Reverse();
  828. return m_pPath[nEndNode].m_dLength;
  829. }
  830. // 计算一个点到所有点的最短路径. 采用Dijkstra算法
  831. // 参数bWeight表示是否考虑方向权重
  832. // 如果nEndNode不等于-1, 则只计算nNode到nEndNode的最短路径,
  833. private bool CalcPath( int nNode, int nEndNode , bool bWeight )
  834. {
  835. if ( nNode < 0 || nNode >= m_arrNodes.Count )
  836. return false;
  837. int i, j, nNodeNum;
  838. int nLink;
  839. byte[] pMark = null; // 处理标志数组
  840. nNodeNum = m_arrNodes.Count;
  841. if ( nNodeNum == 0 )
  842. return true;
  843. pMark = new byte[nNodeNum];
  844. for ( i = 0; i < nNodeNum; i++ )
  845. pMark[i] = 0;
  846. // (1) 初始化
  847. // 初始化路径数组, 类的构造函数会将长度置为-1, 前趋结点为-1
  848. m_pPath = null;
  849. m_pPath = new NetPath[nNodeNum];
  850. for ( i = 0; i < nNodeNum; i++ )
  851. m_pPath[i] = new NetPath();
  852. // 自身
  853. m_pPath[nNode].m_dLength = 0;
  854. m_pPath[nNode].m_nPreNode = nNode;
  855. // 对于与该结点直接相连的点, 初始化路径长度为连接弧度的阻力
  856. for ( i = 0; i < ((NetNode)m_arrNodes[nNode]).m_arrLinks.Count; i++ )
  857. {
  858. nLink = ((NetEdge)((NetNode)m_arrNodes[nNode]).m_arrLinks[i]).nLink;
  859. if ( ((NetLink)m_arrLinks[nLink]).m_nFNode == nNode )
  860. {
  861. // 路径长度, 正向
  862. m_pPath[((NetLink)m_arrLinks[nLink]).m_nTNode].m_dLength = 
  863. bWeight ? ((NetLink)m_arrLinks[nLink]).m_fFromImp  : ((NetLink)m_arrLinks[nLink]).m_fLength;
  864. // 前趋结点, 如果长度<0, 无前趋结点
  865. if ( m_pPath[((NetLink)m_arrLinks[nLink]).m_nTNode].m_dLength < 0 )
  866. m_pPath[((NetLink)m_arrLinks[nLink]).m_nTNode].m_nPreNode = -1;
  867. else
  868. m_pPath[((NetLink)m_arrLinks[nLink]).m_nTNode].m_nPreNode = nNode;
  869. }
  870. else if ( ((NetLink)m_arrLinks[nLink]).m_nTNode == nNode )
  871. {
  872. // 路径长度, 逆向
  873. m_pPath[((NetLink)m_arrLinks[nLink]).m_nFNode].m_dLength = 
  874. bWeight ? ((NetLink)m_arrLinks[nLink]).m_fToImp : ((NetLink)m_arrLinks[nLink]).m_fLength;
  875. // 前趋结点, 如果长度<0, 无前趋结点
  876. if ( m_pPath[((NetLink)m_arrLinks[nLink]).m_nFNode].m_dLength < 0 )
  877. m_pPath[((NetLink)m_arrLinks[nLink]).m_nFNode].m_nPreNode = -1;
  878. else
  879. m_pPath[((NetLink)m_arrLinks[nLink]).m_nFNode].m_nPreNode = nNode;
  880. }
  881. }
  882. // 开始处理
  883. int nMinNode;
  884. double dDist, dMinDist;
  885. for ( i = 0; i < nNodeNum; i++ )
  886. {
  887. // (2) 在未处理结点中找出距离值最小的结点
  888. nMinNode = -1;
  889. dMinDist = 1.7e+308;
  890. for ( j = 0; j < nNodeNum; j++ )
  891. {
  892. // 让过自身
  893. if ( j == nNode )
  894. continue;
  895. // 让过不连通结点
  896. if ( m_pPath[j].m_dLength < 0 ) // <0 表示无穷大
  897. continue;
  898. // 让过处理过的结点
  899. if ( pMark[j] == 1 )
  900. continue;
  901. // 在未处理过的结点中找出距离最小的
  902. if ( m_pPath[j].m_dLength < dMinDist )
  903. {
  904. dMinDist = m_pPath[j].m_dLength;
  905. nMinNode = j;
  906. }
  907. }
  908. // 如果没找到, 则表示与其他点不连通
  909. if ( nMinNode == -1 )
  910. {
  911. pMark = null;
  912. return true;
  913. }
  914. // 处理该距离最小的点
  915. pMark[nMinNode] = 1;
  916. // (3) 调整余下的结点的最短路径
  917. for ( j = 0; j < nNodeNum; j++ )
  918. {
  919. // 让过自身
  920. if ( j == nNode )
  921. continue;
  922. // 让过处理过的结点
  923. if ( pMark[j] == 1 )
  924. continue;
  925. // 调整未处理过的结点的最短路径
  926. // 计算直接相连的结点间的距离
  927. dDist = GetConnectedDistance( nMinNode, j, bWeight );
  928. if ( dDist < 0 ) // 不连通
  929. continue;
  930. // 更新未处理过的结点的最短路径
  931. if ( m_pPath[j].m_dLength < 0 || 
  932. m_pPath[j].m_dLength > m_pPath[nMinNode].m_dLength + dDist )
  933. {
  934. m_pPath[j].m_dLength = m_pPath[nMinNode].m_dLength + dDist ;
  935. m_pPath[j].m_nPreNode = nMinNode;
  936. }
  937. }
  938. }
  939. pMark = null;
  940. return true;
  941. }
  942. // 得到两个结点直接连接的距离, 不直接连接则返回-1
  943. // 返回的结果考虑了方向权重, 因此是与nNode1,nNode2的参数顺序有关的
  944. private double GetConnectedDistance( int nNode1, int nNode2, bool bWeight )
  945. {
  946. if ( nNode1 < 0 || nNode1 >= m_arrNodes.Count )
  947. return -1;
  948. if ( nNode2 < 0 || nNode2 >= m_arrNodes.Count )
  949. return -1;
  950. if ( nNode1 == nNode2 )
  951. return 0;
  952. int nLink;
  953. double dDistance;
  954. double dMinDist = 1.7e+308;
  955. int nRes = 0;
  956. int i = 0;
  957. // 遍历与结点1相连的弧段, 判断弧段的另一端的结点是否为结点2, 是则返回距离
  958. for ( i = 0; i < ((NetNode)m_arrNodes[nNode1]).m_arrLinks.Count; i++ )
  959. {
  960. nLink = ((NetEdge)((NetNode)m_arrNodes[nNode1]).m_arrLinks[i]).nLink;
  961. if ( ((NetLink)m_arrLinks[nLink]).m_nFNode == nNode1 )
  962. {
  963. if ( ((NetLink)m_arrLinks[nLink]).m_nTNode == nNode2 )
  964. {
  965. dDistance = bWeight ? ((NetLink)m_arrLinks[nLink]).m_fFromImp : ((NetLink)m_arrLinks[nLink]).m_fLength;
  966. if ( dDistance < dMinDist )
  967. {
  968. dMinDist = dDistance;
  969. nRes = 1;
  970. }
  971. }
  972. }
  973. else if ( ((NetLink)m_arrLinks[nLink]).m_nTNode == nNode1 )
  974. {
  975. if ( ((NetLink)m_arrLinks[nLink]).m_nFNode == nNode2 )
  976. {
  977. dDistance = bWeight ? ((NetLink)m_arrLinks[nLink]).m_fToImp : ((NetLink)m_arrLinks[nLink]).m_fLength;
  978. if ( dDistance < dMinDist )
  979. {
  980. dMinDist = dDistance;
  981. nRes = -1;
  982. }
  983. }
  984. }
  985. }
  986. if ( nRes == 0 )
  987. return -1;
  988. return dMinDist;
  989. }
  990. // 由结点生成路径的结果图层
  991. // 参数含义: pNodes: 网络分析结果结点集
  992. //           nNum: 结点数目
  993. //           szLayerName: 结果图层名称
  994. //           bWeight TRUE为计算考虑方向权重最优路径, FALSE为不考虑方向权重的最短路径
  995. private bool CreateResultPath( ArrayList pNodes, out NetLine line, bool bWeight )
  996. {
  997. line = new NetLine(m_layer);
  998. int i, j;
  999. // 将分析结果结点集转换为线加入到结果图层中
  1000. int nNum;
  1001. int nRes;
  1002. int nNode1, nNode2, nLink;
  1003. double dDistance, dRatio;
  1004. double dTotalImp;
  1005. nNum = pNodes.Count;
  1006. int idLine;
  1007. dTotalImp = 0;
  1008. for ( i = 0; i < nNum-1; i++ )
  1009. {
  1010. // 得到连接两个结点的最短弧段
  1011. nNode1 = (int)pNodes[i];
  1012. nNode2 = (int)pNodes[i+1];
  1013. nRes = IsConnectedDirectly( nNode1, nNode2, out nLink, out dDistance, bWeight );
  1014. // 不连通则返回false. 这种情况理论上是不可能出现的.
  1015. if ( nRes == 0 )
  1016. {
  1017. return false;
  1018. }
  1019. if ( nLink == -1 )
  1020. continue;
  1021. // 将该弧段的结点按路径顺序加入到结果图层的线中去
  1022. idLine = ((NetLink)m_arrLinks[nLink]).m_GeoID;
  1023. NetLine tmpLine = new NetLine(m_layer);
  1024. tmpLine.GetLineData( idLine );
  1025. // 只加入起始结点和终止结点之间的点
  1026. double dDist;
  1027. int nSegIndex1, nSegIndex2;
  1028. NetPoint ptNearst1, ptNearst2, ptTemp;
  1029. ptTemp = new NetPoint();
  1030. ptTemp.x= ((NetNode)m_arrNodes[nNode1]).x;
  1031. ptTemp.y= ((NetNode)m_arrNodes[nNode1]).y;
  1032. tmpLine.GetNearestPoint( ptTemp, out ptNearst1, out nSegIndex1, out dDist );
  1033. ptTemp.x= ((NetNode)m_arrNodes[nNode2]).x;
  1034. ptTemp.y= ((NetNode)m_arrNodes[nNode2]).y;
  1035. tmpLine.GetNearestPoint( ptTemp, out ptNearst2, out nSegIndex2, out dDist );
  1036. dRatio = ((NetLink)m_arrLinks[nLink]).m_fLength / tmpLine.CalcLength();
  1037. if ( nRes == 1 )
  1038. {
  1039. // 正向
  1040. line.AddCoord( ptNearst1 );
  1041. for ( j = nSegIndex1; j < nSegIndex2; j++ )
  1042. line.AddCoord( (NetPoint)tmpLine.m_pCoords[j+1] );
  1043. line.AddCoord( ptNearst2 );
  1044. dTotalImp += ((NetLink)m_arrLinks[nLink]).m_fFromImp;
  1045. }
  1046. else if ( nRes == -1 )
  1047. {
  1048. // 逆向
  1049. line.AddCoord( ptNearst1 );
  1050. for ( j = nSegIndex1; j > nSegIndex2; j-- )
  1051. line.AddCoord( (NetPoint)tmpLine.m_pCoords[j] );
  1052. line.AddCoord( ptNearst2 );
  1053. dTotalImp += ((NetLink)m_arrLinks[nLink]).m_fToImp;
  1054. }
  1055. tmpLine = null;
  1056. if ( line.m_pCoords.Count < 2 )
  1057. {
  1058. line.m_pCoords.Clear();
  1059. continue;
  1060. }
  1061. }
  1062. return true;
  1063. }
  1064. // 判断两个结点是否直接相连. 即两个结点在同一条弧段上
  1065. // 返回值: 0  不直接连通
  1066. //         1  直接连通, 且从nNode1到nNode2为正向连接
  1067. //         -1 直接连通, 且从nNode1到nNode2为逆向连接
  1068. // 如果两个结点直接连通, 则同时返回连接两个结点的弧段nLink,以及直接连通的最小阻力加权距离dDistance
  1069. // 如果不直接连通, 则nLink=-1, dDistance=-1
  1070. private int IsConnectedDirectly( int nNode1, int nNode2, out int nLink, out double dDistance, bool bWeight )
  1071. {
  1072. nLink = -1;
  1073. dDistance = 0;
  1074. if ( nNode1 < 0 || nNode1 >= m_arrNodes.Count )
  1075. return 0;
  1076. if ( nNode2 < 0 || nNode2 >= m_arrNodes.Count )
  1077. return 0;
  1078. if ( nNode1 == nNode2 )
  1079. return 1;
  1080. int i = 0;
  1081. int nRes = 0;
  1082. int nMinLink = -1;
  1083. double dMinDist = 1.7e+308;
  1084. // 遍历与结点1相连的弧段, 判断弧段的另一端的结点是否为结点2
  1085. for ( i = 0; i < ((NetNode)m_arrNodes[nNode1]).m_arrLinks.Count; i++ )
  1086. {
  1087. nLink = ((NetEdge)((NetNode)m_arrNodes[nNode1]).m_arrLinks[i]).nLink;
  1088. if ( ((NetLink)m_arrLinks[nLink]).m_nFNode == nNode1 )
  1089. {
  1090. if ( ((NetLink)m_arrLinks[nLink]).m_nTNode == nNode2 )
  1091. {
  1092. dDistance = bWeight ?((NetLink)m_arrLinks[nLink]).m_fFromImp : ((NetLink)m_arrLinks[nLink]).m_fLength;
  1093. if ( dDistance < dMinDist )
  1094. {
  1095. dMinDist = dDistance;
  1096. nMinLink = nLink;
  1097. nRes = 1;
  1098. }
  1099. }
  1100. }
  1101. else if ( ((NetLink)m_arrLinks[nLink]).m_nTNode == nNode1 )
  1102. {
  1103. if ( ((NetLink)m_arrLinks[nLink]).m_nFNode == nNode2 )
  1104. {
  1105. dDistance = bWeight ? ((NetLink)m_arrLinks[nLink]).m_fToImp : ((NetLink)m_arrLinks[nLink]).m_fLength;
  1106. if ( dDistance < dMinDist )
  1107. {
  1108. dMinDist = dDistance;
  1109. nMinLink = nLink;
  1110. nRes = -1;
  1111. }
  1112. }
  1113. }
  1114. }
  1115. if ( nRes == 0 )
  1116. {
  1117. nLink = -1;
  1118. dDistance = -1;
  1119. return 0;
  1120. }
  1121. nLink = nMinLink;
  1122. dDistance = dMinDist;
  1123. return nRes;
  1124. }
  1125. // 去除加入的站点或中心点. UnloadStops与LoadStops必须一一对应
  1126. private bool UnloadStops()
  1127. {
  1128. int i, j;
  1129. int nLink, nNode;
  1130. double dAngle;
  1131. // 清空站点表
  1132. m_arrStops.Clear();
  1133. // 利用备份数据, 恢复弧段表和结点表, 并清除备份数据
  1134. for ( i = 0; i < m_arrLinkBackups.Count; i++ )
  1135. {
  1136. nLink = ((NetLinkBackup)m_arrLinkBackups[i]).m_nIndex;
  1137. // 恢复弧段表
  1138. ((NetLink)m_arrLinks[nLink]).Copy( ((NetLinkBackup)m_arrLinkBackups[i]).m_Link );
  1139. // 恢复点表
  1140. nNode = ((NetLink)m_arrLinks[nLink]).m_nTNode;
  1141. dAngle = ((NetNode)m_arrNodes[nNode]).GetLinkAngle( nLink );
  1142. for ( j = ((NetNode)m_arrNodes[nNode]).m_arrLinks.Count-1; j >=0 ; j-- )
  1143. {
  1144. if ( ((NetEdge)((NetNode)m_arrNodes[nNode]).m_arrLinks[j]).nLink >= m_nLinkNum )
  1145. {
  1146. ((NetNode)m_arrNodes[nNode]).m_arrLinks.RemoveAt( j );
  1147. }
  1148. }
  1149. ((NetNode)m_arrNodes[nNode]).Add( nLink, dAngle );
  1150. }
  1151. m_arrLinkBackups.Clear();
  1152. m_pPath = null;
  1153. return true;
  1154. }
  1155. }
  1156. }