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