说明:利用Visio模具和具有站场基本信息的xml文件,生成点线拓扑,从而使用模具绘制完整的站场图

    拓扑类

    1. namespace InfoEdits
    2. {
    3. public class Point
    4. {
    5. public int ID { get; set; }//点id
    6. public int TrackID { get; set; }//直股轨道编号
    7. public int Track2ID { get; set; }//弯股轨道编号
    8. public double X { get; set; }//X坐标
    9. public double Y { get; set; }//Y坐标
    10. public double KiloPos { get; set; }//公里标
    11. public double Lat { get; set; }//纬度(数字度单位)
    12. public double Lon { get; set; }//经度(数字度)
    13. public double Hgt { get; set; }//高度(m)
    14. public double DeltaPos { get; set; }//距离轨道起点的距离
    15. public int ForwardID { get; set; } //前向指针(按照下行方向),虚拟终点的下行方向为999
    16. public int ReverseID { get; set; }//后向指针(上行方向),虚拟起点的上行方向为999
    17. public int SideID { get; set; } = 999;//侧向--主要针对道岔点的弯轨,无岔区段设置为999
    18. public DeviceType pointType { get; set; } = DeviceType.PiecePoint;
    19. public SwitchDirection SwitchDirection { get; set; } = SwitchDirection.None;//一般情况下点不为岔尖点
    20. public string Tag { get; set; }//特殊备注,如道岔的编号
    21. public int VisioIndex { get; set; }
    22. public bool IsConnected { get; set; }
    23. public Point()
    24. {
    25. }
    26. public Point(double lat,double lon)
    27. {
    28. this.Lat = lat;
    29. this.Lon = lon;
    30. }
    31. public Point(double lat, double lon,int ID)
    32. {
    33. this.Lat = lat;
    34. this.Lon = lon;
    35. this.ID = ID;
    36. }
    37. public Point(double lat, double lon, int ID,DeviceType type)
    38. {
    39. this.Lat = lat;
    40. this.Lon = lon;
    41. this.ID = ID;
    42. this.pointType = type;
    43. if(type==DeviceType.StartPoint)//如果是起点
    44. {
    45. this.ReverseID = 999;
    46. this.ForwardID = ID + 1;
    47. }
    48. else if(type==DeviceType.EndPoint)//如果是终点
    49. {
    50. this.ReverseID = ID - 1;
    51. this.ForwardID = 999;
    52. }
    53. else if(type == DeviceType.PiecePoint)
    54. {
    55. this.ReverseID = ID - 1;
    56. this.ForwardID = ID + 1;
    57. }
    58. }
    59. public Point(double lat, double lon, int ID,int TrackId, DeviceType type)
    60. {
    61. this.Lat = lat;
    62. this.Lon = lon;
    63. this.TrackID = TrackId;
    64. this.Track2ID = TrackId;
    65. this.ID = ID;
    66. this.pointType = type;
    67. if (type == DeviceType.StartPoint)//如果是起点
    68. {
    69. this.ReverseID = 999;
    70. this.ForwardID = ID + 1;
    71. }
    72. else if (type == DeviceType.EndPoint)//如果是终点
    73. {
    74. this.ReverseID = ID - 1;
    75. this.ForwardID = 999;
    76. }
    77. else if (type == DeviceType.PiecePoint)
    78. {
    79. this.ReverseID = ID - 1;
    80. this.ForwardID = ID + 1;
    81. }
    82. }
    83. public Point(double lat, double lon, int ID,int Trackid, DeviceType type, int reverseID, int forwardID)
    84. {
    85. this.Lat = lat;
    86. this.Lon = lon;
    87. this.TrackID = Trackid;
    88. this.Track2ID = Trackid;
    89. this.ID = ID;
    90. this.pointType = type;
    91. this.ReverseID = reverseID;
    92. this.ForwardID = forwardID;
    93. }
    94. public Point(double lat, double lon, int ID, DeviceType type,int reverseID,int forwardID)
    95. {
    96. this.Lat = lat;
    97. this.Lon = lon;
    98. this.ID = ID;
    99. this.pointType = type;
    100. this.ReverseID = reverseID;
    101. this.ForwardID = forwardID;
    102. }
    103. }
    104. public class Line
    105. {
    106. public int ID { get; set; }
    107. public Point StartPoint { get; set; }
    108. public Point EndPoint { get; set; }
    109. public Line()
    110. { }
    111. public Line(int ID)
    112. {
    113. this.ID = ID;
    114. }
    115. public Line(int ID,Point startPoint,Point endPoint)
    116. {
    117. this.ID = ID;
    118. this.StartPoint = startPoint;
    119. this.EndPoint = endPoint;
    120. }
    121. }
    122. public class Track
    123. {
    124. public int ID { get; set; }
    125. public double StartX { get; set; }//起始X坐标
    126. public double StartY { get; set; }//起始Y坐标
    127. public double EndX { get; set; }//结束X坐标
    128. public double EndY { get; set; }//结束Y坐标
    129. public double Y { get; set; } = 0.0;//直股的Y坐标
    130. public double Deg { get; set; }//作为图元直线应该有deg弧度
    131. public double Length { get; set; }//长度
    132. public int[] inflectionPoints { get; set; } = new int[2];
    133. public InfoEdits.Point[] InflectionPoints { get; set; }//侧线-的拐点
    134. public List<Point> Points { get; set; }//点集
    135. public List<Line> Lines { get; set; }//线集
    136. public DeviceType Type { get; set; } = DeviceType.DownsideTrack;
    137. /// <summary>
    138. /// 找到侧线轨道的两个弯轨点
    139. /// </summary>
    140. /// <param name="Points"></param>
    141. /// <returns></returns>
    142. public void SetInflectionPoints()
    143. {
    144. if (this.Type == DeviceType.Side)
    145. {
    146. int[] flags = new int[2];
    147. List<int> ff = new List<int>();
    148. double temp = 0.0;
    149. int tempid = 0;
    150. for (int i = 1; i < Points.Count; i++)
    151. {
    152. double bear = GetBear(Points[i - 1].Lat, Points[i].Lat, Points[i - 1].Lon, Points[i].Lon);
    153. Console.WriteLine(bear.ToString());
    154. if (i == 1)
    155. {
    156. temp = bear;
    157. tempid = Points[i].ID;
    158. }
    159. else if (Math.Abs(bear - temp) < 0.0174533)//设置阈值为1度
    160. {
    161. temp = bear;
    162. }
    163. else if (Math.Abs(bear - temp) > 0.0174533)//1度
    164. {
    165. temp = bear;
    166. tempid = Points[i - 1].ID;
    167. ff.Add(tempid);
    168. }
    169. Console.WriteLine(Math.Abs(bear - temp).ToString());
    170. }
    171. ff.Sort();
    172. this.inflectionPoints[0] = ff[0];
    173. this.inflectionPoints[1] = ff[1];
    174. InfoEdits.Point[] pp = new InfoEdits.Point[2];
    175. pp[0] = this.Points.Find(a => a.ID == ff[0]);
    176. pp[1] = this.Points.Find(a => a.ID == ff[1]);
    177. this.InflectionPoints = pp;
    178. //this.CurvePoints[0] = this.Points.Find(a => a.ID == ff[0]);
    179. //this.CurvePoints[1] = this.Points.Find(a => a.ID == ff[1]);
    180. }
    181. }
    182. /// <summary>
    183. /// 得到两点之间的航向角(弧度-3.14-3.14)
    184. /// </summary>
    185. /// <param name="LatA"></param>
    186. /// <param name="LatB"></param>
    187. /// <param name="LngA"></param>
    188. /// <param name="LngB"></param>
    189. /// <returns></returns>
    190. private double GetBear(double LatA, double LatB, double LngA, double LngB)
    191. {
    192. double bear = 0.0;
    193. //
    194. double E = LngB - LngA;
    195. double N = LatB - LatA;
    196. bear = Math.Atan2(E, N);//得到弧度-3.14~3.14
    197. return bear;
    198. }
    199. }
    200. //public class TrackPiece
    201. //{
    202. // public int ID { get; set; }
    203. // public int TrackID { get; set; }
    204. // public int StartPointID { get; set; }
    205. // public int EndPointID { get; set; }
    206. // public double Bear { get; set; }
    207. // public double Length { get; set; }
    208. //}
    209. public class Balise
    210. {
    211. public int ID { get; set; }
    212. public double DeltaPos { get; set; }
    213. public double X { get; set; }
    214. public double Y { get; set; }
    215. public int TrackID { get; set; }
    216. public BaliseDirection Direction { get; set; } = BaliseDirection.temp;//预留
    217. public BaliseProperty Property { get; set; } = BaliseProperty.temp;
    218. public int Type { get; set; }
    219. public int VisioIndex { get; set; }
    220. }
    221. public class Topology
    222. {
    223. public string Name { get; set; }//拓扑名称
    224. public int ID { get; set; }//车站编号
    225. public string UpLinkStationName { get; set; }
    226. public string DownLinkStationName { get; set; }
    227. public Direction Direction { get; set; } = 0;//初始设置为纬度升序
    228. public List<Track> Tracks { get; set; }
    229. public List<Point> Points { get; set; }
    230. public List<Line> Lines { get; set; }
    231. public List<Balise> Balises { get; set; }
    232. public List<int> TrackID { get; set; }//正线ID
    233. public List<int> CrossLineID { get; set; }//渡线ID
    234. public List<int> SideID { get; set; }//侧线ID
    235. public double Scale { get; set; } = 100;//比例尺,默认设置100
    236. public Dictionary<int, InfoEdits.Point[]> Dic { get; set; } = new Dictionary<int, InfoEdits.Point[]>();//保存直线和正线的直线方程
    237. /// <summary>
    238. /// 更新Track上的点
    239. /// </summary>
    240. public void UpdateTrack()
    241. {
    242. List<InfoEdits.Point> points = this.Points;
    243. foreach (InfoEdits.Track t in this.Tracks)
    244. {
    245. t.Points.ForEach
    246. (
    247. a => points.Find(b => b.ID == a.ID)
    248. );
    249. t.Y = t.Points.First().Y;
    250. if (t.InflectionPoints != null)
    251. {
    252. t.InflectionPoints = new InfoEdits.Point[2] { t.Points.Find(b => b.ID == t.inflectionPoints[0]), t.Points.Find(b => b.ID == t.inflectionPoints[1]) };
    253. t.Y = t.Points.Find(a => a.ID == t.inflectionPoints[0] + 1).Y;
    254. }
    255. }
    256. }
    257. public void UpdateLinearDic()
    258. {
    259. this.Dic.Clear();
    260. foreach(Track t in this.Tracks)
    261. {
    262. if(t.Type==DeviceType.UpsideTrack||t.Type==DeviceType.DownsideTrack)
    263. {
    264. Dic.Add(t.ID, new Point[2] { t.Points.First(), t.Points.Last() });
    265. }
    266. else if(t.Type==DeviceType.Side)
    267. {
    268. if (!t.inflectionPoints.Contains(0))
    269. {
    270. Dic.Add(t.ID, t.InflectionPoints);
    271. }
    272. }
    273. }
    274. }
    275. }
    276. public enum DeviceType
    277. {
    278. PiecePoint=0,//轨道点
    279. StartPoint=1,//虚拟起点
    280. Signal=2,//信号机
    281. Switch=3,//道岔
    282. Crossline=4,//渡线
    283. SingleTrack=5,//轨道区段
    284. Side=6,//侧线
    285. EndPoint=7,//虚拟终点
    286. Balise=8,//应答器
    287. UpsideTrack=9,
    288. DownsideTrack=10
    289. }
    290. //按照正线的下行方向
    291. public enum Direction
    292. {
    293. LatAscend=0,//纬度升序,站型1
    294. LatDescend=1,//纬度降序,站型2
    295. LngAscend =2,//经度升序,站型3
    296. LngDesecnd =3,//经度降序,站型4
    297. }
    298. public enum SwitchDirection
    299. {
    300. Reverse=0,//岔尖所在轨道的位置偏移减小的方向(上行方向)
    301. Forward = 1,//岔尖所在轨道的位置偏移增长方向(下行方向)
    302. None=999//非道岔
    303. }
    304. public enum BaliseDirection
    305. {
    306. bothway=0,
    307. reverse=1,
    308. forward=2,
    309. temp=3
    310. }
    311. public enum BaliseProperty
    312. {
    313. VB=0,//Virtual Balise
    314. Entity=1,//实体应答器
    315. VB_2=2,//有区间数据的虚拟应答器
    316. temp=3//预留
    317. }
    318. }

    思路见:
    语雀内容

    1. #region 列控数据表绘图方法
    2. /// <summary>
    3. /// 从列控工程数据表Excel表出图
    4. /// </summary>
    5. /// <param name="selectedFiles"></param>
    6. private void DrawVisio(List<string> selectedFiles)
    7. {
    8. List<TxtPoint> allPoints = new List<TxtPoint>();
    9. //利用循环遍历出key和value
    10. //选择的文件---现在暂时必须只能是列控数据Excel表中的
    11. foreach (string f in selectedFiles)
    12. {
    13. allPoints.AddRange((List<TxtPoint>)Hashtable[f]);
    14. }
    15. double minkilo = allPoints.Min(a => a.KiloPos);//最小公里标---定x轴
    16. double maxkilo = allPoints.Max(a => a.KiloPos);//最大公里标
    17. //之后考虑是否在Excel转Txtpoint的时候就提取轨道编号
    18. //需要提取字符串中的数字
    19. int trackidmin = allPoints.Min(a => ExtractNumbersFormString(a.TrackName));//最小的轨道编号-定y轴
    20. int trackidmax = allPoints.Max(a => ExtractNumbersFormString(a.TrackName));//最大的轨道编号
    21. //分类别保存
    22. List<TxtPoint> joints = allPoints.Where(a => a.type == PointType.Joint).ToList();//绝缘节列表
    23. List<TxtPoint> signals = allPoints.Where(a => a.type == PointType.Signal).ToList();//信号机列表
    24. List<TxtPoint> ssignals = signals.Where(a => a.TypeName.Contains("S")).ToList();//上行信号机列表
    25. List<TxtPoint> xsignals = signals.Where(a => a.TypeName.Contains("X")).ToList();//下行信号机列表
    26. List<TxtPoint> switchs = allPoints.Where(a => a.type == PointType.Switch).ToList();//道岔列表
    27. double deltakilo = maxkilo - minkilo;//主要为了和Page的宽度设置比例尺
    28. int[] PosY = new int[] { 5, 6, 7, 8, 9, 10 };//直接定好根据轨道编号y坐标,索引值即轨道编号,即编号为1时y坐标为2
    29. //公里标作为x坐标
    30. //y坐标按照轨道编号来定
    31. Visio.Shape shape;
    32. //用轨道名称号重新分组
    33. var group = joints.GroupBy(a => ExtractNumbersFormString(a.TrackName)).ToList();
    34. foreach (IGrouping<int, TxtPoint> g in group)
    35. {
    36. List<int> shapeIndex = new List<int>();//每个组都有一个新的指数值表
    37. List<TxtPoint> points = g.ToList();
    38. points = points.OrderBy(a => a.KiloPos).ToList();//根据公里标重新排序
    39. foreach (TxtPoint p in points)
    40. {
    41. int trackid = ExtractNumbersFormString(p.TrackName);
    42. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Joint"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid]);
    43. p.VisShapeIndex = shape.Index;//记住图形的index
    44. }
    45. for (int j = 0; j < points.Count - 1; j++)//连接每个shape
    46. {
    47. Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage;
    48. Shape BeginShape = visPage.Shapes[points[j].VisShapeIndex];
    49. Shape EndShape = visPage.Shapes[points[j + 1].VisShapeIndex];
    50. ConnectedShapes(BeginShape, EndShape);
    51. points[j].IsConnected = true;
    52. points[j + 1].IsConnected = true;
    53. }
    54. }
    55. //用一个字典保存每个轨道的两个点
    56. Dictionary<int, TxtPoint[]> dic = new Dictionary<int, TxtPoint[]>();
    57. foreach (IGrouping<int, TxtPoint> g in group)
    58. {
    59. List<TxtPoint> points = g.ToList();
    60. if (points.Count >= 2)
    61. {
    62. points = points.OrderBy(a => a.KiloPos).ToList();//根据公里标重新排序
    63. TxtPoint[] p2 = new TxtPoint[2] { points[0], points[1] };//选取前两个
    64. dic.Add(ExtractNumbersFormString(points[0].TrackName), p2);
    65. }
    66. }
    67. //设置信号机的位置
    68. //上行信号机在轨道的下方,所以y要减0.1左右
    69. //同时还要考虑X/S信号机
    70. foreach (TxtPoint p in ssignals)
    71. {
    72. int trackid = ExtractNumbersFormString(p.TypeName);
    73. if (trackid == 0)//如果是S信号机
    74. {
    75. trackid = ReturnTrackId(p, dic);
    76. }
    77. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Signal2.0"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid] - 0.2);
    78. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*2";
    79. shape.Characters.Begin = 0;
    80. shape.Characters.End = 0;
    81. shape.Characters.Text = p.TypeName;
    82. p.VisShapeIndex = shape.Index;
    83. }
    84. foreach (TxtPoint p in xsignals)
    85. {
    86. int trackid = ExtractNumbersFormString(p.TypeName);
    87. if (trackid == 0)//如果是X信号机
    88. {
    89. trackid = ReturnTrackId(p, dic);
    90. }
    91. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Signal1.0"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid] + 0.2);
    92. //添加设备的名称/文本
    93. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*2";
    94. shape.Characters.Begin = 0;
    95. shape.Characters.End = 0;
    96. shape.Characters.Text = p.TypeName;
    97. p.VisShapeIndex = shape.Index;
    98. }
    99. //先设置Switch的位置,根据每个轨道两个点的直线来设置道岔的位置,并且保存Index值
    100. List<int> switchIndex = new List<int>();
    101. //将道岔按照公里标大小排序
    102. switchs = switchs.OrderBy(a => a.KiloPos).ToList();
    103. //比如江仓站就是13957;
    104. foreach (TxtPoint p in switchs)
    105. {
    106. int trackid = ReturnTrackId(p, dic);//通过比较道岔点与轨道直线的距离判定属于哪个轨道
    107. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Switch"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid]);
    108. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*5";
    109. shape.Characters.Begin = 0;
    110. shape.Characters.End = 0;
    111. shape.Characters.Text = p.TypeName;
    112. p.TrackName = trackid.ToString();
    113. p.VisShapeIndex = shape.Index;
    114. }
    115. //连接各个Switch,思路是按照公里标相近的道岔,判断是否是同一个轨道---其实这样是不对的
    116. //1-9,3-5
    117. for (int i = 0; i < switchs.Count; i++)
    118. {
    119. if (!switchs[i].IsConnected)//如果图形没有连接过
    120. {
    121. Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage
    122. //当两个道岔轨道编号不等且时退出
    123. for (int j = i; j < switchs.Count; j++)
    124. {
    125. int track1Id = Convert.ToInt32(switchs[i].TrackName);
    126. int track2Id = Convert.ToInt32(switchs[j].TrackName);
    127. int delta = Math.Abs(track1Id - track2Id);
    128. //跳过轨道名称相同的和跳过不是相邻轨道的(差1)
    129. if (delta == 0 || delta > 1)
    130. {
    131. continue;
    132. }
    133. //跳过已经连接了的轨道
    134. if (switchs[j].IsConnected)
    135. {
    136. continue;
    137. }
    138. else if (!switchs[j].IsConnected)
    139. {
    140. Shape BeginShape = visPage.Shapes[switchs[i].VisShapeIndex];
    141. Shape EndShape = visPage.Shapes[switchs[j].VisShapeIndex];
    142. ConnectedShapes(BeginShape, EndShape);
    143. switchs[i].IsConnected = true;
    144. switchs[j].IsConnected = true;
    145. break;
    146. }
    147. }
    148. }
    149. else
    150. {
    151. break;
    152. }
    153. }
    154. }
    155. #endregion
    156. #region 电子地图xml文件绘制站场图
    157. private void DrawTopology(Station station)
    158. {
    159. InfoEdits.Topology Topo = InitialTopoElements(station);//初始设置点线的连接关系
    160. SetTrackX(ref Topo);//设置正线的X坐标
    161. SetSwitchDirection(station, ref Topo);//设置道岔的开叉方向--以此为依据设置轨道的层数、Y坐标
    162. Topo.UpdateTrack();//更新轨道的点
    163. SetTrackY(ref Topo);//设置直股的Y坐标
    164. //SetTrackY2(ref Topo);//设置直股的Y坐标
    165. Topo.UpdateTrack();//更新Track中的点
    166. SetAllCrossLineXY(ref Topo);//设置渡线的坐标;
    167. //检查XY坐标
    168. CheckXY(Topo.Points);
    169. SetSideXY(ref Topo);//设置侧线的XY坐标
    170. Topo.UpdateTrack();
    171. //UpdateTrack(ref Topo);
    172. SetBalisePos(ref Topo);//设置应答器的逻辑坐标
    173. DrawTopology(ref Topo);
    174. CheckXY(Topo.Points);
    175. this.Topo = Topo;
    176. }
    177. /// <summary>
    178. /// 初步建立拓扑点线连接图,点的编号和前后向类型
    179. /// </summary>
    180. /// <param name="station"></param>
    181. private InfoEdits.Topology InitialTopoElements(Station station)
    182. {
    183. //初次添加轨道、点、线
    184. InfoEdits.Topology topo = new InfoEdits.Topology();
    185. topo.Name = station.StationProperties.StationName;
    186. topo.UpLinkStationName = station.StationProperties.UplinkStationNum.ToString();
    187. topo.DownLinkStationName = station.StationProperties.DownlinkStationNum.ToString();
    188. List<InfoEdits.Track> tracks = new List<InfoEdits.Track>();
    189. List<InfoEdits.Point> Points = new List<InfoEdits.Point>();
    190. List<InfoEdits.Line> Lines = new List<InfoEdits.Line>();
    191. int index = 1;
    192. for (int i = 0; i < station.TrackInfo.Tracks.Count; i++)
    193. {
    194. Track tc = station.TrackInfo.Tracks[i];
    195. InfoEdits.Track t = new InfoEdits.Track();
    196. List<int> trackids = new List<int>();
    197. List<int> CrosslineId = new List<int>();
    198. List<int> SideId = new List<int>();
    199. t.ID = tc.TrackID;
    200. if(tc.TrackType == 1)
    201. {
    202. t.Type = InfoEdits.DeviceType.SingleTrack;
    203. trackids.Add(t.ID);
    204. }
    205. else if(tc.TrackType==2)
    206. {
    207. t.Type = InfoEdits.DeviceType.UpsideTrack;
    208. trackids.Add(t.ID);
    209. }
    210. else if (tc.TrackType == 3)
    211. {
    212. t.Type = InfoEdits.DeviceType.DownsideTrack;//正线轨道
    213. trackids.Add(t.ID);
    214. }
    215. else if(tc.TrackType==4)
    216. {
    217. t.Type = InfoEdits.DeviceType.Side;//侧线
    218. SideId.Add(t.ID);
    219. }
    220. else if(tc.TrackType==5)
    221. {
    222. t.Type = InfoEdits.DeviceType.Crossline;//渡线
    223. CrosslineId.Add(t.ID);
    224. }
    225. topo.TrackID = trackids;
    226. topo.SideID = SideId;
    227. topo.CrossLineID = CrosslineId;
    228. double startlat = tc.StartLat;
    229. double startlon = tc.StartLon;
    230. List<InfoEdits.Point> points = new List<InfoEdits.Point>();
    231. List<InfoEdits.Line> lines = new List<InfoEdits.Line>();
    232. if (tc.TrackType == 4 || tc.TrackType == 5)//如果是侧线或者是渡线,第一个point设置为Switch
    233. {
    234. //暂时ReverseID设置为0
    235. int indexx = index;
    236. InfoEdits.Point pp;
    237. for (int j = 0; j < station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces.Count; j++)
    238. {
    239. TrackPiece tp = station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces[j];
    240. if (j == 0)//是第一个点
    241. {
    242. pp=new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.Switch);
    243. points.Add(pp);
    244. }
    245. else
    246. {
    247. pp = new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.PiecePoint);
    248. points.Add(pp);
    249. }
    250. index++;
    251. }
    252. pp = new InfoEdits.Point(tc.EndLat / 3600000.0, tc.EndLon / 3600000.0, index, t.ID, InfoEdits.DeviceType.Switch, 0, index + 1);
    253. points.Add(pp);
    254. index++;
    255. for (int j=indexx;j<index-1;j++)
    256. {
    257. lines.Add(new InfoEdits.Line(indexx, points.Find(a=>a.ID==indexx), points.Find(a => a.ID == indexx+1)));
    258. }
    259. }
    260. else //如果是正线类型,设置起始点为StartPoint
    261. {
    262. int indexx = index;
    263. InfoEdits.Point pp;
    264. for (int j = 0; j < station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces.Count; j++)
    265. {
    266. TrackPiece tp = station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces[j];
    267. if (j == 0)//是第一个点
    268. {
    269. pp = new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.StartPoint);
    270. points.Add(pp);
    271. }
    272. else
    273. {
    274. pp = new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.PiecePoint);
    275. points.Add(pp);
    276. }
    277. index++;
    278. }
    279. pp = new InfoEdits.Point(tc.EndLat / 3600000.0, tc.EndLon / 3600000.0, index, t.ID, InfoEdits.DeviceType.EndPoint);
    280. points.Add(pp);
    281. index++;
    282. for (int j = indexx; j < index - 1; j++)
    283. {
    284. lines.Add(new InfoEdits.Line(indexx, points.Find(a => a.ID == indexx), points.Find(a => a.ID == indexx + 1)));
    285. }
    286. }
    287. t.Points = points;
    288. t.Lines = lines;
    289. tracks.Add(t);
    290. Points.AddRange(points);
    291. Lines.AddRange(lines);
    292. }
    293. topo.Tracks = tracks;
    294. topo.Points = Points;
    295. topo.Lines = Lines;
    296. if(tracks.First().StartX<tracks.Last().StartX)
    297. {
    298. topo.Direction = InfoEdits.Direction.LatAscend;
    299. }
    300. else
    301. {
    302. topo.Direction = InfoEdits.Direction.LatDescend;
    303. }
    304. topo.UpdateTrack();
    305. foreach(InfoEdits.Track t in topo.Tracks)
    306. {
    307. t.SetInflectionPoints();//如果是侧线设置拐点
    308. }
    309. //设置道岔点的前向后向和侧向ID
    310. //拓扑更新直线方程
    311. topo.UpdateLinearDic();
    312. var switchTracks = station.TrackInfo.Tracks.Where(a => a.TrackType > 3);//侧线和渡线
    313. foreach (Track t in switchTracks)
    314. {
    315. var tt = tracks.Find(a => a.ID == t.TrackID);
    316. SetSwitchPoint(ref tt, tracks,topo.Dic);
    317. }
    318. //检查--发现拓扑仍然不对
    319. Check(topo);
    320. //判断两个点之间是否有多余插入的点,重新排序。
    321. //注意不仅点要排序,其实Line也要排序,其实line有重叠部分,在拓扑点安排好之前不应生成Line的编号
    322. foreach(Track t in station.TrackInfo.Tracks)
    323. {
    324. if(t.TrackType<=3)
    325. {
    326. var group = topo.Points.GroupBy(a => a.TrackID == t.TrackID);
    327. foreach (IGrouping<bool, InfoEdits.Point> g in group)
    328. {
    329. if (g.Key == true)
    330. {
    331. //直股编号上的所有点集合,重新排列前后顺序
    332. List<InfoEdits.Point> points = (List<InfoEdits.Point>)g.ToList();
    333. //首先根据纬度方向排序
    334. //如果拓扑正线的方向是纬度升序
    335. if (topo.Direction == InfoEdits.Direction.LatAscend|| topo.Direction == InfoEdits.Direction.LngDesecnd)
    336. {
    337. points = points.OrderBy(a => a.Lat).ToList();
    338. for (int j = 0; j < points.Count; j++)
    339. {
    340. if (points[j].pointType == InfoEdits.DeviceType.StartPoint)
    341. {
    342. points[j].ForwardID = points[j + 1].ID;
    343. }
    344. else if (points[j].pointType == InfoEdits.DeviceType.EndPoint)
    345. {
    346. points[j].ReverseID = points[j - 1].ID;
    347. }
    348. else
    349. {
    350. points[j].ReverseID = points[j - 1].ID;
    351. points[j].ForwardID = points[j + 1].ID;
    352. }
    353. }
    354. }
    355. //如果拓扑的方向是纬度降序
    356. else if (topo.Direction == InfoEdits.Direction.LatDescend || topo.Direction == InfoEdits.Direction.LngAscend)
    357. {
    358. points = points.OrderByDescending(a => a.Lat).ToList();
    359. for (int j = 0; j < points.Count; j++)
    360. {
    361. if (points[j].pointType == InfoEdits.DeviceType.StartPoint)
    362. {
    363. points[j].ForwardID = points[j + 1].ID;
    364. }
    365. else if (points[j].pointType == InfoEdits.DeviceType.EndPoint)
    366. {
    367. points[j].ReverseID = points[j - 1].ID;
    368. }
    369. else
    370. {
    371. points[j].ReverseID = points[j - 1].ID;
    372. points[j].ForwardID = points[j + 1].ID;
    373. }
    374. }
    375. }
    376. }
    377. }
    378. }
    379. }
    380. topo.Balises = GetBalises(station);
    381. //检查基本正确
    382. return topo;
    383. }
    384. private List<InfoEdits.Balise> GetBalises(Station station)
    385. {
    386. List<Balise> balises = station.TrainControlData.BaliseData.Balises;
    387. List<InfoEdits.Balise> bs = new List<InfoEdits.Balise>();
    388. foreach(Balise b in balises)
    389. {
    390. InfoEdits.Balise b_2 = new InfoEdits.Balise();
    391. b_2.ID = balises.IndexOf(b) + 1;
    392. b_2.TrackID = b.BaliseTrackNum;
    393. b_2.DeltaPos = b.BalisePos;
    394. int direction = b.BaliseProperty & 192;
    395. b_2.Direction = (InfoEdits.BaliseDirection)direction;
    396. int prop = b.BaliseProperty & 3;
    397. b_2.Property = (InfoEdits.BaliseProperty)prop;
    398. b_2.Type = b.BaliseLoc;
    399. bs.Add(b_2);
    400. }
    401. return bs;
    402. }
    403. /// <summary>
    404. /// 更新Track上的点
    405. /// </summary>
    406. /// <param name="topo"></param>
    407. private void UpdateTrack(ref InfoEdits.Topology topo)
    408. {
    409. List<InfoEdits.Point> points = topo.Points;
    410. foreach(InfoEdits.Track t in topo.Tracks)
    411. {
    412. t.Points.ForEach
    413. (
    414. a => points.Find(b => b.ID == a.ID)
    415. );
    416. }
    417. }
    418. private string Check(InfoEdits.Topology topo)
    419. {
    420. string s = "";
    421. foreach (InfoEdits.Track t in topo.Tracks)
    422. {
    423. s += t.ID.ToString() + "\r\n";
    424. foreach (InfoEdits.Point p in t.Points)
    425. {
    426. s += string.Format("编号{0},前向点{1},后向点{2},侧边点{3},直股编号{4},弯股编号{5}", p.ID, p.ReverseID, p.ForwardID, p.SideID, p.TrackID, p.Track2ID) + "\r\n";
    427. }
    428. }
    429. Console.WriteLine(s);
    430. return s;
    431. }
    432. private string Check(List<InfoEdits.Point> points)
    433. {
    434. string s = "";
    435. foreach (InfoEdits.Point p in points)
    436. {
    437. s += string.Format("编号{0},前向点{1},后向点{2},侧边点{3},直股编号{4},弯股编号{5}", p.ID, p.ReverseID, p.ForwardID, p.SideID, p.TrackID, p.Track2ID) + "\r\n";
    438. }
    439. Console.WriteLine(s);
    440. return s;
    441. }
    442. /// <summary>
    443. /// 检查点
    444. /// </summary>
    445. /// <param name="points"></param>
    446. /// <returns></returns>
    447. private string Check2(List<InfoEdits.Point> points)
    448. {
    449. string s = "";
    450. foreach (InfoEdits.Point p in points)
    451. {
    452. s += string.Format("编号{0},道岔方向{1},点类型{2},备注{3}",p.ID, p.SwitchDirection,p.pointType.ToString(),p.Tag) + "\r\n";
    453. }
    454. Console.WriteLine(s);
    455. return s;
    456. }
    457. ///// <summary>
    458. ///// 设置道岔点的前后向节点指针
    459. ///// </summary>
    460. ///// <param name="track"></param>
    461. ///// <param name="tracks"></param>
    462. ///// <param name="dic"></param>
    463. //private void SetSwitchPoint(ref InfoEdits.Track track,List<InfoEdits.Track> tracks,Dictionary<int,InfoEdits.Point[]> dic)
    464. //{
    465. // int tracknum = track.ID;//所处轨道的编号
    466. // var startPoint = track.Points.First();
    467. // var endPoint = track.Points.Last();
    468. // if (startPoint.pointType == InfoEdits.DeviceType.Switch)
    469. // {
    470. // int trackID = ReturnTrackId(startPoint, dic);//dic中只保存正线直线方程
    471. // InfoEdits.Track t = tracks.Find(a => a.ID == trackID);
    472. // int[] ids = ReturnClosedID(startPoint, t.Points);
    473. // startPoint.SideID = track.Points[1].ID;
    474. // //dictionary保存的正线直线一定在道岔的两端,所以暂时不判断
    475. // startPoint.ReverseID = ids[0];
    476. // startPoint.ForwardID = ids[1];
    477. // startPoint.TrackID = trackID;//直股ID
    478. // }
    479. // if (endPoint.pointType == InfoEdits.DeviceType.Switch)
    480. // {
    481. // int trackID = ReturnTrackId(endPoint, dic);//dic中只保存正线直线方程
    482. // InfoEdits.Track t = tracks.Find(a => a.ID == trackID);
    483. // int[] ids = ReturnClosedID(endPoint, t.Points);
    484. // endPoint.SideID = track.Points.Last().ID - 1;//倒数第二个点的ID
    485. // endPoint.ReverseID = ids[0];
    486. // endPoint.ForwardID = ids[1];
    487. // endPoint.TrackID = trackID;//直股ID
    488. // }
    489. //}
    490. /// <summary>
    491. /// 设置道岔点的前后向节点指针
    492. /// </summary>
    493. /// <param name="track"></param>
    494. /// <param name="tracks"></param>
    495. /// <param name="dic"></param>
    496. private void SetSwitchPoint(ref InfoEdits.Track track, List<InfoEdits.Track> tracks, Dictionary<int, InfoEdits.Point[]> dic)
    497. {
    498. int tracknum = track.ID;//所处轨道的编号
    499. var startPoint = track.Points.First();
    500. var endPoint = track.Points.Last();
    501. if (startPoint.pointType == InfoEdits.DeviceType.Switch)
    502. {
    503. int trackID = ReturnTrackId(startPoint, dic);//dic中只保存正线直线方程
    504. startPoint.SideID = track.Points[1].ID;
    505. //dictionary保存的正线直线一定在道岔的两端,所以暂时不判断
    506. startPoint.TrackID = trackID;//直股ID
    507. }
    508. if (endPoint.pointType == InfoEdits.DeviceType.Switch)
    509. {
    510. int trackID = ReturnTrackId(endPoint, dic);//dic中只保存正线直线方程
    511. endPoint.SideID = track.Points.Last().ID - 1;//倒数第二个点的ID
    512. endPoint.TrackID = trackID;//直股ID
    513. }
    514. }
    515. /// <summary>
    516. /// 根据xml文件中的道岔设置相应的道岔点的开岔方向
    517. /// </summary>
    518. /// <param name="station"></param>
    519. /// <param name="Topo"></param>
    520. private void SetSwitchDirection(Station station,ref InfoEdits.Topology Topo)
    521. {
    522. var switchPoints = Topo.Points.Where(a=>a.pointType==InfoEdits.DeviceType.Switch).ToList();
    523. List<Switch> switches = station.TrainControlData.SwitchData.Switches;
    524. foreach(InfoEdits.Point p in switchPoints)
    525. {
    526. var switchs = switches.Where(a => a.SwitchPosTrackNum == p.TrackID&&a.SwitchReverseTrackNum == p.Track2ID);
    527. foreach(Switch s in switchs)
    528. {
    529. if(Math.Abs(s.SwitchPos-p.X*10000)<=300)//阈值300cm-3m
    530. {
    531. p.Tag = "SW" + s.SwitchNum.ToString();
    532. p.SwitchDirection = (InfoEdits.SwitchDirection)s.SwitchDirection;
    533. }
    534. }
    535. }
    536. //捡漏
    537. var swip = switchPoints.FindAll(a => a.SwitchDirection == InfoEdits.SwitchDirection.None);
    538. foreach(InfoEdits.Point p in swip)
    539. {
    540. var switchs = switches.Where(a => a.SwitchPosTrackNum == p.TrackID && a.SwitchReverseTrackNum == p.Track2ID);
    541. foreach (Switch s in switchs)
    542. {
    543. if (Math.Round(s.SwitchPos/10000 - p.X,0) == -1)//阈值300cm-3m
    544. {
    545. p.Tag = "SW" + s.SwitchNum.ToString();
    546. p.SwitchDirection = (InfoEdits.SwitchDirection)s.SwitchDirection;
    547. }
    548. }
    549. }
    550. Check2(switchPoints);
    551. }
    552. /// <summary>
    553. /// 返回中心点与点集合距离的最小点,此方法针对已经确定centerP点处于正线的中间
    554. /// </summary>
    555. /// <param name="centerP">中心点</param>
    556. /// <param name="points">要比较的点集</param>
    557. /// <returns></returns>
    558. private int[] ReturnClosedID(InfoEdits.Point centerP,List<InfoEdits.Point> points)
    559. {
    560. int[] ids = new int[2];
    561. //points = points.OrderBy(a => a.Lat).ToList();//根据纬度排序
    562. points = points.Where(a => a != centerP).ToList();//排除本身
    563. Dictionary<int,double> dic = new Dictionary<int, double>();
    564. List<double> distance = new List<double>();
    565. foreach(InfoEdits.Point p in points)
    566. {
    567. double dis = GetDistance(centerP.Lat, centerP.Lon, p.Lat, p.Lon);
    568. distance.Add(dis);
    569. dic.Add(p.ID, dis);
    570. }
    571. distance =distance.OrderBy(a=>a).ToList();//按照距离升序排序。
    572. var key1 = dic.Where(q => q.Value == distance[0]).Select(a => a.Key).ToList<int>();
    573. var key2 = dic.Where(q => q.Value == distance[1]).Select(a => a.Key).ToList<int>();
    574. if(key1[0]<key2[0])
    575. {
    576. ids[0] = key1[0];
    577. ids[1] = key2[0];
    578. }
    579. else if(key1[0]>key2[0])
    580. {
    581. ids[0] = key2[0];
    582. ids[1] = key1[0];
    583. }
    584. return ids;
    585. }
    586. /// <summary>
    587. /// 根据直股上两点的距离设置相对位置X坐标
    588. /// </summary>
    589. /// <param name="topo"></param>
    590. private void SetTrackX(ref InfoEdits.Topology topo)
    591. {
    592. //设置Y坐标,先找到正线
    593. foreach (InfoEdits.Track t in topo.Tracks.FindAll(a => a.Type == InfoEdits.DeviceType.SingleTrack||a.Type==InfoEdits.DeviceType.DownsideTrack||a.Type==InfoEdits.DeviceType.UpsideTrack))
    594. {
    595. var points = topo.Points.FindAll(a => a.TrackID == t.ID);
    596. //设置正线的x坐标;
    597. double lat = 0.0;
    598. double lng = 0.0;
    599. if (topo.Direction == InfoEdits.Direction.LatDescend)
    600. {
    601. points = points.OrderByDescending(a => a.Lat).ToList();
    602. lat = points.First().Lat;
    603. lng = points.First().Lon;
    604. }
    605. else if (topo.Direction == InfoEdits.Direction.LatAscend)
    606. {
    607. points = points.OrderBy(a => a.Lat).ToList();
    608. lat = points.First().Lat;
    609. lng = points.First().Lon;
    610. }
    611. foreach (InfoEdits.Point p in points)
    612. {
    613. double length = GetDistance(lat, lng, p.Lat, p.Lon);
    614. //p.X = length / 100;
    615. p.X = length / topo.Scale;
    616. }
    617. }
    618. }
    619. /// <summary>
    620. /// 根据道岔的开岔方向设置直股的Y坐标
    621. /// </summary>
    622. /// <param name="topo"></param>
    623. private void SetTrackY(ref InfoEdits.Topology topo)
    624. {
    625. List<InfoEdits.Point> points = new List<InfoEdits.Point>();
    626. List<InfoEdits.Point> switchs = new List<InfoEdits.Point>();
    627. double[] PosY = new double[topo.Tracks.Count];
    628. if (topo.Direction == InfoEdits.Direction.LatAscend)//纬度升序
    629. {
    630. switchs =topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderBy(a => a.Lat).ToList();
    631. }
    632. else if (topo.Direction == InfoEdits.Direction.LatDescend)//纬度降序
    633. {
    634. switchs = topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderByDescending(a => a.Lat).ToList();
    635. }
    636. PosY[0] = 5;//设置图纸上正线的Y坐标为5
    637. //遍历正线和侧线轨道
    638. //找到同属于一个所有道岔点,其中包括了弯轨是侧线或者渡线的道岔点
    639. foreach (InfoEdits.Point p in switchs)
    640. {
    641. if (p.SwitchDirection == InfoEdits.SwitchDirection.Forward)//下行方向
    642. {
    643. //如果道岔点连接的是侧线,即单动道岔
    644. InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));
    645. if (tc.Type == InfoEdits.DeviceType.Side)
    646. {
    647. if (PosY[p.TrackID - 1] != 0 && PosY[p.Track2ID - 1] == 0)//(PosY[t.ID - 1]!=0)
    648. {
    649. PosY[p.Track2ID - 1] = PosY[p.TrackID - 1] - 1;//PosY[t.ID - 1] - 1;//Y坐标-1
    650. }
    651. }
    652. //如果道岔点连接的是渡线
    653. else if (tc.Type == InfoEdits.DeviceType.Crossline)
    654. {
    655. int nextid = tc.Points.Last().TrackID;//渡线最后一个点
    656. if (PosY[p.TrackID - 1] != 0&& PosY[nextid - 1]==0)//(PosY[t.ID - 1] != 0)
    657. {
    658. PosY[nextid - 1] = PosY[p.TrackID - 1] - 1;//PosY[t.ID - 1] - 1;//Y坐标-1
    659. }
    660. }
    661. }
    662. else if (p.SwitchDirection == InfoEdits.SwitchDirection.Reverse)//上行方向
    663. {
    664. //如果道岔点连接的是侧线,即单动道岔
    665. InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));
    666. if (tc.Type == InfoEdits.DeviceType.Side)
    667. {
    668. if (PosY[p.TrackID - 1] != 0&& PosY[p.Track2ID - 1]==0) //(PosY[t.ID - 1] != 0)
    669. {
    670. PosY[p.Track2ID - 1] = PosY[p.TrackID - 1] + 1;//PosY[t.ID - 1] + 1;//Y坐标-1
    671. }
    672. }
    673. //如果道岔点连接的是渡线
    674. else if (tc.Type == InfoEdits.DeviceType.Crossline)
    675. {
    676. int nextid = tc.Points.Last().TrackID;
    677. if (PosY[p.TrackID - 1] != 0&&PosY[nextid - 1] == 0)//(PosY[t.ID - 1] != 0)
    678. {
    679. PosY[nextid - 1] = PosY[p.TrackID - 1] + 1;//PosY[t.ID - 1] + 1;//Y坐标+1
    680. }
    681. }
    682. }
    683. }
    684. foreach(double a in PosY)
    685. {
    686. int index = PosY.FindIndex(i=>i==a);
    687. var track = topo.Tracks.Find(i => i.ID == index + 1);
    688. track.Y = a;
    689. }
    690. //设置了正线和侧线直股的坐标即道岔点的Y坐标
    691. foreach (InfoEdits.Track a in topo.Tracks)
    692. {
    693. if(a.Type == InfoEdits.DeviceType.SingleTrack || a.Type == InfoEdits.DeviceType.DownsideTrack || a.Type == InfoEdits.DeviceType.UpsideTrack)
    694. {
    695. var pps = topo.Points.FindAll(b => b.TrackID == a.ID);
    696. foreach(InfoEdits.Point p in pps)
    697. {
    698. p.Y = PosY[a.ID - 1];
    699. }
    700. }
    701. else if(a.Type==InfoEdits.DeviceType.Side)
    702. {
    703. var pps = topo.Points.FindAll(b => b.Track2ID == a.ID&&b.TrackID==b.Track2ID);
    704. foreach (InfoEdits.Point p in pps)
    705. {
    706. p.Y = PosY[a.ID - 1];
    707. }
    708. }
    709. }
    710. CheckXY(topo.Points);
    711. }
    712. /// <summary>
    713. /// 根据道岔的开岔方向设置直股的Y坐标
    714. /// </summary>
    715. /// <param name="topo"></param>
    716. private void SetTrackY2(ref InfoEdits.Topology topo)
    717. {
    718. List<InfoEdits.Point> points = new List<InfoEdits.Point>();
    719. List<InfoEdits.Point> switchs = new List<InfoEdits.Point>();
    720. double[] PosY = new double[topo.Tracks.Count];
    721. if (topo.Direction == InfoEdits.Direction.LatAscend)//纬度升序
    722. {
    723. switchs = topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderBy(a => a.Lat).ToList();
    724. }
    725. else if (topo.Direction == InfoEdits.Direction.LatDescend)//纬度降序
    726. {
    727. switchs = topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderByDescending(a => a.Lat).ToList();
    728. }
    729. PosY[0] = 5;//设置图纸上正线的Y坐标为5
    730. //遍历正线和侧线轨道
    731. //找到同属于一个所有道岔点,其中包括了弯轨是侧线或者渡线的道岔点
    732. foreach (InfoEdits.Point p in switchs)
    733. {
    734. int track1id = p.TrackID;//直股id
    735. InfoEdits.Point[] track1points = topo.Dic[track1id];
    736. double angle1 = GetBear2(track1points[0].Lat, track1points[1].Lat, track1points[0].Lon, track1points[0].Lon);
    737. InfoEdits.Point forwardPoint = topo.Points.Find(a => a.ID == p.SideID);
    738. if (forwardPoint.ID < p.ID)//如果p点的侧边点编号比自己小,即p是股道的最后一个点,停止计算
    739. {
    740. continue;
    741. }
    742. double angle2 = GetBear2(p.Lat, forwardPoint.Lat, p.Lon, forwardPoint.Lon);
    743. double delta = angle2 - angle1;//夹角
    744. if (delta < 0)
    745. {
    746. InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));
    747. if(tc.Type==InfoEdits.DeviceType.Side)
    748. {
    749. int track2id = p.Track2ID;
    750. PosY[track2id - 1] = PosY[track1id - 1] + 1;
    751. }
    752. else
    753. {
    754. int track2id = tc.Points.Last().TrackID;
    755. PosY[track2id - 1] = PosY[track1id - 1] + 1;
    756. }
    757. }
    758. else if (delta > 0)
    759. {
    760. InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));
    761. if (tc.Type == InfoEdits.DeviceType.Side)
    762. {
    763. int track2id = p.Track2ID;
    764. PosY[track2id - 1] = PosY[track1id - 1] - 1;
    765. }
    766. else
    767. {
    768. int track2id = tc.Points.Last().TrackID;
    769. PosY[track2id - 1] = PosY[track1id - 1] - 1;
    770. }
    771. }
    772. }
    773. foreach (double a in PosY)
    774. {
    775. int index = PosY.FindIndex(i => i == a);
    776. var track = topo.Tracks.Find(i => i.ID == index + 1);
    777. track.Y = a;
    778. }
    779. //设置了正线和侧线直股的坐标即道岔点的Y坐标
    780. foreach (InfoEdits.Track a in topo.Tracks)
    781. {
    782. if (a.Type == InfoEdits.DeviceType.SingleTrack || a.Type == InfoEdits.DeviceType.DownsideTrack || a.Type == InfoEdits.DeviceType.UpsideTrack)
    783. {
    784. var pps = topo.Points.FindAll(b => b.TrackID == a.ID);
    785. foreach (InfoEdits.Point p in pps)
    786. {
    787. p.Y = PosY[a.ID - 1];
    788. }
    789. }
    790. else if (a.Type == InfoEdits.DeviceType.Side)
    791. {
    792. var pps = topo.Points.FindAll(b => b.Track2ID == a.ID && b.TrackID == b.Track2ID);
    793. foreach (InfoEdits.Point p in pps)
    794. {
    795. p.Y = PosY[a.ID - 1];
    796. }
    797. }
    798. }
    799. CheckXY(topo.Points);
    800. }
    801. private void SetAllCrossLineXY(ref InfoEdits.Topology Topo)
    802. {
    803. var tracks = Topo.Tracks.FindAll(a => a.Type == InfoEdits.DeviceType.Crossline);
    804. foreach(InfoEdits.Track t in tracks)
    805. {
    806. InfoEdits.Point[] PointAB = new InfoEdits.Point[2] { t.Points.First(), t.Points.Last() };
    807. for (int i = 1; i < t.Points.Count - 1; i++)
    808. {
    809. var PointC = Topo.Points.Find(a=>a.ID==t.Points[i].ID);
    810. double[] xy = PointBetweenPoints(PointC, PointAB);
    811. PointC.X = xy[0];
    812. PointC.Y = xy[1];
    813. }
    814. }
    815. }
    816. /// <summary>
    817. /// 主要用来计算斜线上点的XY坐标
    818. /// </summary>
    819. /// <param name="PointC"></param>
    820. /// <param name="Points">[0]-PointA;[1]-PointB</param>
    821. /// <returns></returns>
    822. private double[] PointBetweenPoints(InfoEdits.Point PointC,InfoEdits.Point[] Points)
    823. {
    824. double[] xy = new double[2];
    825. InfoEdits.Point PointA = Points[0];
    826. InfoEdits.Point PointB = Points[1];
    827. double deltay = PointB.Y - PointA.Y;
    828. double deltax = PointB.X - PointA.X;
    829. double lengthAB = Math.Abs(GetDistance(PointA.Lat, PointA.Lon, PointB.Lat, PointB.Lon));
    830. double lengthAC = Math.Abs(GetDistance(PointA.Lat, PointA.Lon, PointC.Lat, PointC.Lon));
    831. xy[0] = lengthAC / lengthAB * deltax + PointA.X;
    832. xy[1] = lengthAC / lengthAB * deltay + PointA.Y;
    833. return xy;
    834. }
    835. //侧线上的所有Y已经设置好了
    836. /// <summary>
    837. /// 设置拓扑的侧线的所有点的坐标
    838. /// </summary>
    839. /// <param name="topo"></param>
    840. private void SetSideXY(ref InfoEdits.Topology topo)
    841. {
    842. var side = topo.Tracks.FindAll(a => a.Type == InfoEdits.DeviceType.Side);
    843. foreach (InfoEdits.Track t in side)
    844. {
    845. //获取侧线的两个折点
    846. int[] curvedPoints = ReturnCurvedPoints(t.Points);
    847. InfoEdits.Point A = t.Points.First();
    848. InfoEdits.Point B = t.Points.Last();
    849. //总长
    850. double all = GetDistance(A.Lat, A.Lon, B.Lat, B.Lon);
    851. double allxy = B.X - A.X;
    852. var curvePoint1 = topo.Points.Find(a => a.ID == curvedPoints[0]);
    853. var curvePoint2 = topo.Points.Find(a => a.ID == curvedPoints[1]);
    854. //首先设置折点curvePoint1和curvePoint2的X坐标
    855. //计算弧度
    856. double d = GetDistance(A.Lat, A.Lon, curvePoint1.Lat, curvePoint1.Lon);
    857. double angle = Math.Asin(GetPoint2Line(A, B, curvePoint1) / d);
    858. curvePoint1.X = d * Math.Cos(angle)/topo.Scale+A.X;
    859. d= GetDistance(B.Lat, B.Lon, curvePoint2.Lat, curvePoint2.Lon);
    860. angle = Math.Asin(GetPoint2Line(A, B, curvePoint2) / d);
    861. curvePoint2.X = B.X - d * Math.Cos(angle) / topo.Scale;
    862. //分成三段处理
    863. for (int j = 1; j < t.Points.IndexOf(curvePoint1); j++)
    864. {
    865. double[] PosXY = PointBetweenPoints(t.Points[j], new InfoEdits.Point[2] { A, curvePoint1 });
    866. var point = topo.Points.Find(a => a.ID == t.Points[j].ID);
    867. point.X = PosXY[0];
    868. point.Y = PosXY[1];
    869. }
    870. //直股段
    871. double dis = GetDistance(curvePoint1.Lat, curvePoint1.Lon, curvePoint2.Lat, curvePoint2.Lon);
    872. double dx = curvePoint2.Y - curvePoint1.X;
    873. for (int a = t.Points.IndexOf(curvePoint1) + 1; a < t.Points.IndexOf(curvePoint2); a++)
    874. {
    875. InfoEdits.Point PointA = t.Points[a - 1];
    876. InfoEdits.Point PointB = t.Points[a];
    877. double l = GetDistance(PointA.Lat, PointA.Lon, PointB.Lat, PointB.Lon);
    878. var point = topo.Points.Find(b => b.ID == t.Points[a].ID);
    879. //point.X = curvePoint1.X + l / dis * dx;
    880. point.X = curvePoint1.X + l / Topo.Scale;
    881. }
    882. for (int b = t.Points.IndexOf(curvePoint2) + 1; b < t.Points.Count(); b++)
    883. {
    884. double[] PosXY = PointBetweenPoints(t.Points[b], new InfoEdits.Point[2] { curvePoint2, B });
    885. var point = topo.Points.Find(a => a.ID == t.Points[b].ID);
    886. point.X = PosXY[0];
    887. point.Y = PosXY[1];
    888. }
    889. }
    890. }
    891. private void SetBalisePos(ref InfoEdits.Topology topo)
    892. {
    893. foreach(InfoEdits.Balise b in topo.Balises)
    894. {
    895. var t = topo.Tracks.Find(a => a.ID == b.TrackID);
    896. double startx = t.Points.First().X;
    897. double y = t.Y;
    898. if (t.Type==InfoEdits.DeviceType.UpsideTrack|| t.Type == InfoEdits.DeviceType.DownsideTrack|| t.Type == InfoEdits.DeviceType.SingleTrack)
    899. {
    900. b.X = startx + b.DeltaPos / 100 / topo.Scale;
    901. b.Y = y - 0.1;
    902. }
    903. else if(t.Type==InfoEdits.DeviceType.Side)
    904. {
    905. InfoEdits.Point inflectionPoint1 = t.InflectionPoints[0];
    906. var basex = topo.Tracks.Find(a => a.Type == InfoEdits.DeviceType.DownsideTrack).Points.First().X;
    907. b.X = b.DeltaPos/100/topo.Scale+basex;
    908. b.Y = y - 0.1;
    909. }
    910. }
    911. }
    912. /// <summary>
    913. /// 绘制已经编制好的Topo至Visio图纸
    914. /// </summary>
    915. /// <param name="topo"></param>
    916. private void DrawTopology(ref InfoEdits.Topology topo)
    917. {
    918. SetPointPos(ref topo);//设置所有点(未包括信号机、应答器)
    919. ConnectAllPoints(topo);
    920. SetOthersShape(topo);//设置下行方向,上行车站、下行车站等形状
    921. //SetBalisePos(ref topo);
    922. SetBaliseShape(ref topo);
    923. }
    924. private void ConnectAllPoints(InfoEdits.Topology topo)
    925. {
    926. foreach (InfoEdits.Track t in topo.Tracks)
    927. {
    928. if (t.Type == InfoEdits.DeviceType.SingleTrack || t.Type == InfoEdits.DeviceType.DownsideTrack || t.Type == InfoEdits.DeviceType.UpsideTrack)
    929. {
    930. var points = topo.Points.FindAll(a => a.TrackID == t.ID);
    931. ConnectPoints(points);
    932. }
    933. else
    934. {
    935. var points = topo.Points.FindAll(a => a.Track2ID == t.ID);
    936. ConnectPoints(points);
    937. }
    938. }
    939. }
    940. /// <summary>
    941. /// 遍历拓扑中的所有点并设置XY坐标,记录point的VisioIndex
    942. /// </summary>
    943. /// <param name="topo"></param>
    944. private void SetPointPos(ref InfoEdits.Topology topo)
    945. {
    946. Shape shape;
    947. foreach (InfoEdits.Point p in topo.Points)
    948. {
    949. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Joint"], p.X, p.Y);
    950. p.VisioIndex = shape.Index;//记住图形的index
    951. shape.Characters.Begin = 0;
    952. shape.Characters.End = 0;
    953. if (string.IsNullOrEmpty(p.Tag))
    954. {
    955. shape.Characters.Text = p.ID.ToString();
    956. }
    957. else
    958. {
    959. shape.Characters.Text = p.Tag;
    960. }
    961. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,
    962. (short)VisRowIndices.visRowTextXForm, 6).FormulaU = "90 deg";
    963. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,
    964. (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*10";
    965. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,
    966. (short)VisRowIndices.visRowTextXForm, 0).FormulaU = "Width*-0.8";
    967. }
    968. }
    969. /// <summary>
    970. /// 连接两个Visio绝缘节对象
    971. /// </summary>
    972. /// <param name="points"></param>
    973. private void ConnectPoints(List<InfoEdits.Point> points)
    974. {
    975. for (int j = 0; j < points.Count - 1; j++)
    976. {
    977. Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage;
    978. Shape BeginShape = visPage.Shapes[points[j].VisioIndex];
    979. Shape EndShape = visPage.Shapes[points[j + 1].VisioIndex];
    980. ConnectedShapes(BeginShape, EndShape);
    981. points[j].IsConnected = true;
    982. points[j + 1].IsConnected = true;
    983. }
    984. }
    985. private void SetBaliseShape(ref InfoEdits.Topology topo)
    986. {
    987. Shape shape;
    988. foreach(InfoEdits.Balise b in topo.Balises)
    989. {
    990. string shapename = string.Format("Balise{0}", b.Type);
    991. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters[shapename],b.X, b.Y);
    992. b.VisioIndex = shape.Index;
    993. }
    994. }
    995. private void SetOthersShape(InfoEdits.Topology topo)
    996. {
    997. double minx = topo.Points.Min(a => a.X);
    998. double maxx = topo.Points.Max(a => a.X);
    999. double maxy = topo.Points.Max(a => a.Y);
    1000. double width = 2;
    1001. double height = 0.4;
    1002. double deltay = 2;//Y坐标偏移
    1003. double deltax = 0.8;
    1004. //添加下行方向标志
    1005. Shape shape;
    1006. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Direction"], (minx+maxx)/2, maxy+1);
    1007. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,
    1008. (short)VisRowIndices.visRowXForm1D, 2).FormulaU = "334.30000280175 mm";
    1009. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,
    1010. (short)VisRowIndices.visRowXForm1D, 3).FormulaU = "177.00000147154 mm";
    1011. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowLine, 0).FormulaU = "2 pt";
    1012. shape.Characters.CharProps[7] = 30;
    1013. //添加车站文本,设置无外框线
    1014. shape = axDrawingControl1.Document.Pages[1].DrawRectangle((minx + maxx) / 2 - width / 2+deltax, maxy+height/2+deltay, (minx + maxx) / 2 + width / 2+deltax, maxy - height/2+deltay);
    1015. shape.TextStyle = "Normal";
    1016. shape.LineStyle = "Text Only";
    1017. shape.FillStyle = "Text Only";
    1018. shape.Characters.Begin = 0;
    1019. shape.Characters.End = 0;
    1020. shape.Characters.Text = topo.Name;
    1021. shape.get_CellsSRC((short)VisSectionIndices.visSectionCharacter, 0, 7).FormulaU = "30 pt";
    1022. shape.get_CellsSRC((short)VisSectionIndices.visSectionCharacter, 0, 2).FormulaU = "17";
    1023. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowLine, 2).FormulaU = "0";
    1024. shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowGradientProperties, 4).FormulaU = "FALSE";
    1025. }
    1026. /// <summary>
    1027. /// 得到两点之间的航向角(弧度-3.14-3.14)
    1028. /// </summary>
    1029. /// <param name="LatA"></param>
    1030. /// <param name="LatB"></param>
    1031. /// <param name="LngA"></param>
    1032. /// <param name="LngB"></param>
    1033. /// <returns></returns>
    1034. private double GetBear(double LatA, double LatB, double LngA, double LngB)
    1035. {
    1036. double bear = 0.0;
    1037. //
    1038. double E = LngB - LngA;
    1039. double N = LatB - LatA;
    1040. bear = Math.Atan2(E, N);//得到弧度-3.14~3.14
    1041. return bear;
    1042. }
    1043. /// <summary>
    1044. /// 找到侧线轨道的两个弯轨点
    1045. /// </summary>
    1046. /// <param name="Points"></param>
    1047. /// <returns></returns>
    1048. private int[] ReturnCurvedPoints(List<InfoEdits.Point> Points)
    1049. {
    1050. int[] flags = new int[2];
    1051. List<int> ff = new List<int>();
    1052. double temp = 0.0;
    1053. int tempid = 0;
    1054. for (int i = 1; i < Points.Count; i++)
    1055. {
    1056. double bear = GetBear(Points[i - 1].Lat, Points[i].Lat, Points[i - 1].Lon, Points[i].Lon);
    1057. Console.WriteLine(bear.ToString());
    1058. if (i == 1 )
    1059. {
    1060. temp = bear;
    1061. tempid = Points[i].ID;
    1062. }
    1063. else if (Math.Abs(bear - temp) < 0.0174533)//设置阈值为1度
    1064. {
    1065. temp = bear;
    1066. }
    1067. else if (Math.Abs(bear - temp) > 0.0174533)//1度
    1068. {
    1069. temp = bear;
    1070. tempid = Points[i - 1].ID;
    1071. ff.Add(tempid);
    1072. }
    1073. Console.WriteLine(Math.Abs(bear - temp).ToString());
    1074. }
    1075. ff.Sort();
    1076. flags[0] = ff[0];
    1077. flags[1] = ff[1];
    1078. Console.WriteLine(flags[0].ToString()+","+flags[1].ToString());
    1079. return flags;
    1080. }
    1081. /// <summary>
    1082. /// 检查点坐标
    1083. /// </summary>
    1084. /// <param name="points"></param>
    1085. private void CheckXY(List<InfoEdits.Point> points)
    1086. {
    1087. string s = "";
    1088. foreach(InfoEdits.Point p in points)
    1089. {
    1090. s += string.Format("ID{0},X坐标{1},Y坐标{2}",p.ID, p.X, p.Y) + "\r\n";
    1091. }
    1092. Console.WriteLine(s);
    1093. }
    1094. private void DrawTopo(InfoEdits.Topology topo)
    1095. {
    1096. foreach(InfoEdits.Track t in topo.Tracks)
    1097. {
    1098. var points = topo.Points.FindAll(a => a.TrackID == t.ID);
    1099. if(t.Type == InfoEdits.DeviceType.SingleTrack || t.Type == InfoEdits.DeviceType.DownsideTrack || t.Type == InfoEdits.DeviceType.UpsideTrack)
    1100. {
    1101. double lat = 0.0;
    1102. double lng = 0.0;
    1103. if(topo.Direction==InfoEdits.Direction.LatDescend)
    1104. {
    1105. points = points.OrderByDescending(a => a.Lat).ToList();
    1106. lat = points.First().Lat;
    1107. lng = points.First().Lon;
    1108. }
    1109. else if(topo.Direction == InfoEdits.Direction.LatAscend)
    1110. {
    1111. points = points.OrderBy(a => a.Lat).ToList();
    1112. lat = points.First().Lat;
    1113. lng = points.First().Lon;
    1114. }
    1115. Shape shape;
    1116. foreach (InfoEdits.Point p in points)
    1117. {
    1118. double length = GetDistance(lat, lng, p.Lat, p.Lon);
    1119. p.X = length / 100;
    1120. p.Y = p.TrackID;
    1121. shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Joint"], p.X, p.Y);
    1122. p.VisioIndex = shape.Index;//记住图形的index
    1123. }
    1124. for (int j = 0; j < points.Count - 1; j++)//连接每个shape
    1125. {
    1126. Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage;
    1127. Shape BeginShape = visPage.Shapes[points[j].VisioIndex];
    1128. Shape EndShape = visPage.Shapes[points[j + 1].VisioIndex];
    1129. ConnectedShapes(BeginShape, EndShape);
    1130. BeginShape.Characters.Begin = 0;
    1131. BeginShape.Characters.End = 0;
    1132. BeginShape.Characters.Text = points[j].ID.ToString();
    1133. EndShape.Characters.Begin = 0;
    1134. EndShape.Characters.End = 0;
    1135. EndShape.Characters.Text = points[j + 1].ID.ToString();
    1136. points[j].IsConnected = true;
    1137. points[j + 1].IsConnected = true;
    1138. }
    1139. }
    1140. }
    1141. }
    1142. /// <summary>
    1143. /// 以中心点旋转Angle角度
    1144. /// </summary>
    1145. /// <param name="center">中心点</param>
    1146. /// <param name="p1">待旋转的点</param>
    1147. /// <param name="angle">旋转角度(弧度)</param>
    1148. private void PointRotate(Point center, ref Point p1, double angle)
    1149. {
    1150. double x1 = (p1.X - center.X) * Math.Cos(angle) + (p1.Y - center.Y) * Math.Sin(angle) + center.X;
    1151. double y1 = -(p1.X - center.X) * Math.Sin(angle) + (p1.Y - center.Y) * Math.Cos(angle) + center.Y;
    1152. p1.X = (int)x1;
    1153. p1.Y = (int)y1;
    1154. }
    1155. /// <summary>
    1156. /// 以中心点旋转Angle角度
    1157. /// </summary>
    1158. /// <param name="centerX"></param>
    1159. /// <param name="centerY"></param>
    1160. /// <param name="pointX"></param>
    1161. /// <param name="pointY"></param>
    1162. /// <param name="angle"></param>
    1163. private void PointRotate(double centerX,double centerY,ref double pointX,ref double pointY, double angle)
    1164. {
    1165. double x1 = (pointX - centerX) * Math.Cos(angle) + (pointY - centerY) * Math.Sin(angle) + centerX;
    1166. double y1 = -(pointX - centerX) * Math.Sin(angle) + (pointY - centerY) * Math.Cos(angle) + centerY;
    1167. pointX = x1;
    1168. pointY = y1;
    1169. }
    1170. private double GetBear2(double LatA, double LatB, double LngA, double LngB)
    1171. {
    1172. double bear = 0.0;
    1173. //
    1174. double E = LngB - LngA;
    1175. double N = LatB - LatA;
    1176. bear = Math.Atan2(E, N);//得到弧度-3.14~3.14
    1177. if (bear < 0)
    1178. {
    1179. bear += 6.28;//弧度范围0~6.28
    1180. }
    1181. //改成角度
    1182. //bear=headingA*180/Math.PI;
    1183. //if(bear<0)
    1184. //{
    1185. // bear += 360;//
    1186. //}
    1187. ////方位角转换转弧度
    1188. //bear *= 0.0174533;
    1189. //if(bear>3.14)
    1190. //{
    1191. // bear -= 6.28;
    1192. //}
    1193. return bear;
    1194. }
    1195. public int ExtractNumbersFormString(string s)
    1196. {
    1197. //取出字符串中所有的英文字母
    1198. string strSplit1 = Regex.Replace(s, "[a-z]", "", RegexOptions.IgnoreCase);
    1199. ////取出字符串中所有的数字
    1200. //string strSplit2 = Regex.Replace(FlightNO, "[0-9]", "", RegexOptions.IgnoreCase);
    1201. if (string.IsNullOrEmpty(strSplit1))//避免S/X这种情况,
    1202. {
    1203. return 0;
    1204. }
    1205. else
    1206. {
    1207. return Convert.ToInt32(strSplit1);
    1208. }
    1209. }
    1210. /// <summary>
    1211. /// 连接绝缘节
    1212. /// </summary>
    1213. /// <param name="BeginShape"></param>
    1214. /// <param name="EndShape"></param>
    1215. private void ConnectedShapes(Shape BeginShape,Shape EndShape)
    1216. {
    1217. Visio.Cell BeginXCell;
    1218. Visio.Cell EndXCell;//用来确定连接线连在图形的上下左右,不同图形值不一样
    1219. Page visPage = axDrawingControl1.Document.Pages[1];
    1220. Shape connector = visPage.Drop(visApp.ConnectorToolDataObject, 1.2386, 3.2458);
    1221. BeginXCell = connector.get_CellsU("BeginX");
    1222. EndXCell = BeginShape.get_CellsSRC(7, 0, 0);
    1223. BeginXCell.GlueTo(EndXCell);
    1224. BeginXCell = connector.get_CellsU("EndX");
    1225. EndXCell = EndShape.get_CellsSRC(7, 0, 0);
    1226. BeginXCell.GlueTo(EndXCell);
    1227. }
    1228. /// <summary>
    1229. /// 点P到直线AB的距离,P为线外一点,AB为线段两个端点
    1230. /// </summary>
    1231. /// <param name="pointA"></param>
    1232. /// <param name="pointB"></param>
    1233. /// <param name="P"></param>
    1234. /// <returns></returns>
    1235. private double GetPoint2Line(TxtPoint pointA,TxtPoint pointB, TxtPoint pointP)
    1236. {
    1237. //P为线外一点,AB为线段两个端点
    1238. //求直线方程
    1239. double A = 0, B = 0, C = 0;
    1240. A = pointA.Longtitude/3600000.0 - pointB.Longtitude/3600000.0;
    1241. B = pointB.Latitude/3600000 - pointA.Latitude/3600000;
    1242. C = pointA.Latitude/3600000 * pointB.Longtitude/3600000 - pointA.Longtitude/3600000 * pointB.Latitude/3600000;
    1243. //代入点到直线距离公式
    1244. double distance = 0;
    1245. distance = (Math.Abs(A * pointP.Latitude/3600000 + B * pointP.Longtitude/3600000 + C)) / (Math.Sqrt(A * A + B * B));
    1246. return distance;
    1247. }
    1248. private double GetPoint2Line(InfoEdits.Point pointA, InfoEdits.Point pointB, InfoEdits.Point pointP)
    1249. {
    1250. //P为线外一点,AB为线段两个端点
    1251. //求直线方程
    1252. double A = 0, B = 0, C = 0;
    1253. A = pointA.Lon - pointB.Lon;
    1254. B = pointB.Lat - pointA.Lat;
    1255. C = pointA.Lat * pointB.Lon - pointA.Lon * pointB.Lat;
    1256. //代入点到直线距离公式
    1257. double distance = 0;
    1258. distance = (Math.Abs(A * pointP.Lat + B * pointP.Lon + C)) / (Math.Sqrt(A * A + B * B));
    1259. if (!double.IsNaN(distance))
    1260. {
    1261. return distance;
    1262. }
    1263. else
    1264. {
    1265. return 0;
    1266. }
    1267. }
    1268. private int ReturnTrackId(TxtPoint switchPoint,Dictionary<int,TxtPoint[]> dic)
    1269. {
    1270. int trackid = 0;
    1271. Dictionary<int,double> distance = new Dictionary<int, double>();
    1272. foreach(KeyValuePair<int,TxtPoint[]> pair in dic)
    1273. {
    1274. int key = pair.Key;
    1275. distance.Add(key,(GetPoint2Line(dic[key][0], dic[key][1], switchPoint)));
    1276. }
    1277. var mindis = distance.Values.Min();
    1278. trackid = distance.First(a => a.Value == mindis).Key;
    1279. return trackid;
    1280. }
    1281. /// <summary>
    1282. /// 通过比较直线外点和直线的距离判断属于哪个轨道
    1283. /// </summary>
    1284. /// <param name="pointP"></param>
    1285. /// <param name="dic">int 轨道编号,Point[] 轨道的两个端点</param>
    1286. /// <returns></returns>
    1287. private int ReturnTrackId(InfoEdits.Point pointP, Dictionary<int, InfoEdits.Point[]> dic)
    1288. {
    1289. int trackid = 0;
    1290. Dictionary<int, double> distance = new Dictionary<int, double>();
    1291. foreach (KeyValuePair<int, InfoEdits.Point[]> pair in dic)
    1292. {
    1293. int key = pair.Key;
    1294. distance.Add(key, (GetPoint2Line(dic[key][0], dic[key][1], pointP)));
    1295. }
    1296. var mindis = distance.Values.Min();
    1297. trackid = distance.First(a => a.Value == mindis).Key;
    1298. return trackid;
    1299. }
    1300. /***** 点到直线的距离:P到AB的距离*****/
    1301. //P为线外一点,AB为线段两个端点
    1302. float getDist_P2L(Point pointP, Point pointA, Point pointB)
    1303. {
    1304. //求直线方程
    1305. int A = 0, B = 0, C = 0;
    1306. A = pointA.Y - pointB.Y;
    1307. B = pointB.X - pointA.X;
    1308. C = pointA.X * pointB.Y - pointA.Y * pointB.X;
    1309. //代入点到直线距离公式
    1310. float distance = 0;
    1311. distance = ((float)Math.Abs(A * pointP.X + B * pointP.Y + C)) / ((float)Math.Sqrt(A * A + B * B));
    1312. return distance;
    1313. }
    1314. #endregion