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

📄 netlayer.cs

📁 经典的GIS二次开发系列书籍的一本
💻 CS
📖 第 1 页 / 共 3 页
字号:
using System;
using System.Collections;

namespace MainSystem
{
	public class NetPoint
	{
		public double x;
		public double y;

		public NetPoint()
		{
			x = 0;
			y = 0;
		}

		public NetPoint( double x, double y )
		{
			this.x = x;
			this.y = y;
		}
	}

	public class NetLine
	{
		// 属性
		public ArrayList				m_pCoords = null;
		private MapObjects2.MapLayer	m_layer = null;

		// 构造函数
		public NetLine(MapObjects2.MapLayer layer)
		{
			m_pCoords = new ArrayList();
			m_layer = layer;
		}

		// 计算线的几何长度
		public double CalcLength()
		{
			double	dLength = 0.0 ;		// 保存计算出的线几何长度的结果
			int		loop ;				// 保存循环计数

			// 检查线的有效性
			if ( m_pCoords.Count < 2 )
				return 0.0 ;
			// 计算线的几何长度
			double	dist = 0.0 ;
			for ( loop = 1 ; loop < m_pCoords.Count ; loop ++ )
			{
				dist = Math.Sqrt ( ( ((NetPoint)m_pCoords[loop -1]).x - ((NetPoint)m_pCoords[loop]).x ) * 
					( ((NetPoint)m_pCoords[loop -1]).x - ((NetPoint)m_pCoords[loop]).x ) + 
					( ((NetPoint)m_pCoords[loop -1]).y - ((NetPoint)m_pCoords[loop]).y ) * 
					( ((NetPoint)m_pCoords[loop -1]).y - ((NetPoint)m_pCoords[loop]).y ) ) ;
				dLength += dist ;
			}

			return dLength ;
		}

		// 通过线的id得到线数据
		public bool GetLineData(int id)
		{
			MapObjects2.Recordset rs;
			rs = m_layer.SearchExpression("GeoID = " + id.ToString());

			if (null == rs)
				return false;

			rs.MoveFirst();
 
			if (rs.EOF) 
				return false;

			MapObjects2.Line		line = (MapObjects2.Line)rs.Fields.Item("shape").Value;
			MapObjects2.Points	pts;

			pts = (MapObjects2.Points)line.Parts.Item(0);
  
			m_pCoords.Clear();
 
			for (int i = 0; i < pts.Count; i ++)
			{
				NetPoint pt = new NetPoint(pts.Item(i).X,pts.Item(i).Y);
				m_pCoords.Add(pt); 
			}

			return true;
		}

		// 得到距离某点最近的线段,返回该线段的id
		public int GetNearestLineData( double x, double y)
		{
			MapObjects2.Recordset rs = m_layer.Records;
			MapObjects2.Point		pt = new MapObjects2.PointClass();
			pt.X = x;
			pt.Y = y;

			double	dDist = 9999999;
			int		id = -1;

			rs.MoveFirst(); 
			while(!rs.EOF)
			{
				MapObjects2.Line	line= (MapObjects2.Line)rs.Fields.Item("shape").Value;
				double				d = line.DistanceTo(pt);   					

				if (dDist > d)
				{
					dDist = d;
					string szValue = rs.Fields.Item("Geoid").ValueAsString;
					id = Convert.ToInt32(szValue);
				}
				rs.MoveNext(); 
			}

			if (id != -1)
			{
				if (!GetLineData(id))
					return -1;
			}
			return id;
		}

		public void AddCoord( NetPoint pt )
		{
			m_pCoords.Add( pt );
		}

		public bool IsPtCoincide( NetPoint ptFirst, NetPoint ptSecond )
		{
			if ( Math.Abs(ptFirst.x - ptSecond.x ) <= 0.00000001 && 
				Math.Abs(ptFirst.y - ptSecond.y ) <= 0.00000001 )
				return true;
			return false;
		}

		public void GetNearestPoint( NetPoint ptP, NetPoint ptA, NetPoint ptB,
			out NetPoint ptNearest, out 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 ;

			ptNearest = new NetPoint();
			dDistance = 0;

			if ( IsPtCoincide(ptA,ptB) )
			{
				ptNearest = ptA;
				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 = Math.Sqrt(med) ;	
				dDistance = med ;
				return ;
			}

			if (PA2 < 0.00000001 || PB2 < 0.00000001)
			{
				if(PA2 < 0.00000001)
				{
					med = Math.Sqrt(PA2) ;
					dDistance = med ;
					ptNearest.x = Ax ;
					ptNearest.y = Ay ;
					return ;
				}
				else 
				{
					med = Math.Sqrt(PB2) ;
					dDistance = med ;
					ptNearest.x = Bx ;
					ptNearest.y = By ;
					return ;
				}
			}

			AB = Math.Sqrt(AB2) ;
			PA = Math.Sqrt(PA2) ;
			PB = Math.Sqrt(PB2) ;
			S = (AB + PA + PB) / 2.0 ;
			AREA = S ;
			AREA *= (S - PA) ;
			AREA *= (S - PB) ;
			AREA *= (S - AB) ;
			AREA = Math.Sqrt(AREA) ;
			med = (2.0 * AREA) / AB ;
			dDistance = med ;
	
			med = Ay - By ;
			med1 = Ax - Bx ;
			if(Math.Abs(med) < 0.00000001 || Math.Abs(med1) < 0.00000001)		
			{	
				if(Math.Abs(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 ;
			}
			return;
		}

		public void GetNearestPoint( NetPoint point, out NetPoint ptNearestPoint, 
			out int nSegmentIndex,out double dLeastDistance	)
		{

			int nPointNum = m_pCoords.Count;			
			double dDistance;
			NetPoint ptTemp;
	
			GetNearestPoint( point, (NetPoint)m_pCoords[0],(NetPoint)m_pCoords[1],out ptNearestPoint,out dLeastDistance);
			nSegmentIndex = 0 ;
	
			//遍历每一条弧段来搜索最近的点
			int nIndex ;
			for( nIndex = 1 ; nIndex < nPointNum-1 ; nIndex ++ ) 
			{		
				//得到最近的点
				GetNearestPoint( point, (NetPoint)m_pCoords[0], (NetPoint)m_pCoords[1], out ptTemp, out dDistance ) ;

				//比较最小的距离
				if( dDistance < dLeastDistance )
				{
					dLeastDistance = dDistance ;
					ptNearestPoint = ptTemp ; 
					nSegmentIndex = nIndex ;
				}
			}
			return ;
		}

		// 获得根据给定点分裂线得到的两个部分的比例, 但并不真正分裂线
		// point: 给定点
		// ptNearestPoint: 分裂线时的分裂点 (返回)
		// dRatio: 起始结点部分的比例 (返回)
		public bool GetSplitRatioByNearestPoint( NetPoint point, out NetPoint ptNearest, out double dRatio )
		{
			int nIndex;
			double dDistance;

			int nPointNum = m_pCoords.Count;
			//首先得到最近的点和线段索引
			GetNearestPoint( point, out ptNearest, out nIndex, out dDistance );
	
			//检查线上最近的点是否与首尾点相重合
			if( nIndex == 0 )
			{
				if( IsPtCoincide( ptNearest, (NetPoint)m_pCoords[0] ) )
				{
					dRatio = 0;
					return true;
				}
			}

			if( nIndex == nPointNum-2 )
			{
				if( IsPtCoincide( ptNearest, (NetPoint)m_pCoords[nPointNum-1] ))
				{
					dRatio = 1;
					return true;
				}
			}

			//计算分裂出来的第二条线的长度
			int nLoop;
			double dLength = 0;
			//如果最近点与本线上的下一点不重合,则需将最近点计算在内
			if ( !IsPtCoincide(ptNearest, (NetPoint)m_pCoords[nIndex+1] ) )
			{
				dLength += Math.Sqrt( ( ((NetPoint)m_pCoords[nIndex+1]).x - ptNearest.x ) * 
					( ((NetPoint)m_pCoords[nIndex+1]).x - ptNearest.x ) + 
					( ((NetPoint)m_pCoords[nIndex+1]).y - ptNearest.y ) * 
					( ((NetPoint)m_pCoords[nIndex+1]).y - ptNearest.y )
					);
			}
			for( nLoop = nIndex+2 ; nLoop < nPointNum ; nLoop ++ )
			{
				dLength += Math.Sqrt( ( ((NetPoint)m_pCoords[nLoop]).x - ((NetPoint)m_pCoords[nLoop-1]).x ) * 
					( ((NetPoint)m_pCoords[nLoop]).x - ((NetPoint)m_pCoords[nLoop-1]).x ) + 
					( ((NetPoint)m_pCoords[nLoop]).y - ((NetPoint)m_pCoords[nLoop-1]).y ) * 
					( ((NetPoint)m_pCoords[nLoop]).y - ((NetPoint)m_pCoords[nLoop-1]).y )
					);
			}

			dRatio = 1 - dLength / CalcLength();
			return true;
		}
	}

	public class NetEdge
	{
		public int 		nLink;		// 连接的弧段索引(数组下标索引)
		public float	fAngle;		// 该弧段的水平夹角

		public NetEdge()
		{
			nLink = -1;
			fAngle = 0;
		}
	};

	public class NetNode : NetPoint
	{		
		public ArrayList m_arrLinks = null;	// 与该点连接的弧段数组, 弧段按角度排序
		
		public NetNode() 
		{
			m_arrLinks = new ArrayList();
		}

		public NetNode( double x, double y ) 
		{
			this.x = x;
			this.y = y;
			m_arrLinks = new ArrayList();
		}

		// 加入一个连接的弧段(调用前需确定弧段是连接在该点上的)
		public bool Add( int nLink, double dAngle )
		{
			// 结点连接的弧段按角度排序
			int i = 0;
			for (  i = 0; i < m_arrLinks.Count; i++ )
			{
				if ( dAngle < ((NetEdge)m_arrLinks[i]).fAngle )
					break;
			}
			NetEdge pEdge = new NetEdge();
			pEdge.nLink = nLink;
			pEdge.fAngle = (float)dAngle;
			m_arrLinks.Insert(i, pEdge );

			return true;
		}

		// 删除一个已连接的弧段
		public bool Remove( int nLink )
		{
			for ( int i = 0; i < m_arrLinks.Count ; i++ )
			{
				if ( nLink == ((NetEdge)m_arrLinks[i]).nLink )
				{
					m_arrLinks.RemoveAt( i );
					break;
				}
			}
			return true;
		}

		// 得到一个连接弧段的角度
		public double GetLinkAngle( int nLink )
		{
			for ( int i = 0; i < m_arrLinks.Count ; i++ )
			{
				if ( nLink == ((NetEdge)m_arrLinks[i]).nLink )
				{
					return ((NetEdge)m_arrLinks[i]).fAngle;
				}
			}
			return -1;
		}
	}

	// 网络弧段(链)类
	public class NetLink
	{
		public int m_GeoID;				// 弧段ID(GeoID)
		public int m_nFNode;			// 起始结点(数组下标索引)
		public int m_nTNode;			// 终止结点(数组下标索引)
		public double m_fLength;			// 长度
		public double m_fFromImp;		// 正向阻力(阻力系数*长度 或 (1+阻力系数)*长度)
		public double m_fToImp;			// 逆向阻力

		public NetLink()
		{
			m_GeoID = -1;
			m_nFNode = -1;
			m_nTNode = -1;
			m_fLength = 0;
			m_fFromImp = 0;
			m_fToImp = 0;
		}

		public void 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;
		}

		public bool IsEqual( NetLink link )
		{
			return m_GeoID == link.m_GeoID;

⌨️ 快捷键说明

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