说明:利用Visio模具和具有站场基本信息的xml文件,生成点线拓扑,从而使用模具绘制完整的站场图
拓扑类
namespace InfoEdits{public class Point{public int ID { get; set; }//点idpublic int TrackID { get; set; }//直股轨道编号public int Track2ID { get; set; }//弯股轨道编号public double X { get; set; }//X坐标public double Y { get; set; }//Y坐标public double KiloPos { get; set; }//公里标public double Lat { get; set; }//纬度(数字度单位)public double Lon { get; set; }//经度(数字度)public double Hgt { get; set; }//高度(m)public double DeltaPos { get; set; }//距离轨道起点的距离public int ForwardID { get; set; } //前向指针(按照下行方向),虚拟终点的下行方向为999public int ReverseID { get; set; }//后向指针(上行方向),虚拟起点的上行方向为999public int SideID { get; set; } = 999;//侧向--主要针对道岔点的弯轨,无岔区段设置为999public DeviceType pointType { get; set; } = DeviceType.PiecePoint;public SwitchDirection SwitchDirection { get; set; } = SwitchDirection.None;//一般情况下点不为岔尖点public string Tag { get; set; }//特殊备注,如道岔的编号public int VisioIndex { get; set; }public bool IsConnected { get; set; }public Point(){}public Point(double lat,double lon){this.Lat = lat;this.Lon = lon;}public Point(double lat, double lon,int ID){this.Lat = lat;this.Lon = lon;this.ID = ID;}public Point(double lat, double lon, int ID,DeviceType type){this.Lat = lat;this.Lon = lon;this.ID = ID;this.pointType = type;if(type==DeviceType.StartPoint)//如果是起点{this.ReverseID = 999;this.ForwardID = ID + 1;}else if(type==DeviceType.EndPoint)//如果是终点{this.ReverseID = ID - 1;this.ForwardID = 999;}else if(type == DeviceType.PiecePoint){this.ReverseID = ID - 1;this.ForwardID = ID + 1;}}public Point(double lat, double lon, int ID,int TrackId, DeviceType type){this.Lat = lat;this.Lon = lon;this.TrackID = TrackId;this.Track2ID = TrackId;this.ID = ID;this.pointType = type;if (type == DeviceType.StartPoint)//如果是起点{this.ReverseID = 999;this.ForwardID = ID + 1;}else if (type == DeviceType.EndPoint)//如果是终点{this.ReverseID = ID - 1;this.ForwardID = 999;}else if (type == DeviceType.PiecePoint){this.ReverseID = ID - 1;this.ForwardID = ID + 1;}}public Point(double lat, double lon, int ID,int Trackid, DeviceType type, int reverseID, int forwardID){this.Lat = lat;this.Lon = lon;this.TrackID = Trackid;this.Track2ID = Trackid;this.ID = ID;this.pointType = type;this.ReverseID = reverseID;this.ForwardID = forwardID;}public Point(double lat, double lon, int ID, DeviceType type,int reverseID,int forwardID){this.Lat = lat;this.Lon = lon;this.ID = ID;this.pointType = type;this.ReverseID = reverseID;this.ForwardID = forwardID;}}public class Line{public int ID { get; set; }public Point StartPoint { get; set; }public Point EndPoint { get; set; }public Line(){ }public Line(int ID){this.ID = ID;}public Line(int ID,Point startPoint,Point endPoint){this.ID = ID;this.StartPoint = startPoint;this.EndPoint = endPoint;}}public class Track{public int ID { get; set; }public double StartX { get; set; }//起始X坐标public double StartY { get; set; }//起始Y坐标public double EndX { get; set; }//结束X坐标public double EndY { get; set; }//结束Y坐标public double Y { get; set; } = 0.0;//直股的Y坐标public double Deg { get; set; }//作为图元直线应该有deg弧度public double Length { get; set; }//长度public int[] inflectionPoints { get; set; } = new int[2];public InfoEdits.Point[] InflectionPoints { get; set; }//侧线-的拐点public List<Point> Points { get; set; }//点集public List<Line> Lines { get; set; }//线集public DeviceType Type { get; set; } = DeviceType.DownsideTrack;/// <summary>/// 找到侧线轨道的两个弯轨点/// </summary>/// <param name="Points"></param>/// <returns></returns>public void SetInflectionPoints(){if (this.Type == DeviceType.Side){int[] flags = new int[2];List<int> ff = new List<int>();double temp = 0.0;int tempid = 0;for (int i = 1; i < Points.Count; i++){double bear = GetBear(Points[i - 1].Lat, Points[i].Lat, Points[i - 1].Lon, Points[i].Lon);Console.WriteLine(bear.ToString());if (i == 1){temp = bear;tempid = Points[i].ID;}else if (Math.Abs(bear - temp) < 0.0174533)//设置阈值为1度{temp = bear;}else if (Math.Abs(bear - temp) > 0.0174533)//1度{temp = bear;tempid = Points[i - 1].ID;ff.Add(tempid);}Console.WriteLine(Math.Abs(bear - temp).ToString());}ff.Sort();this.inflectionPoints[0] = ff[0];this.inflectionPoints[1] = ff[1];InfoEdits.Point[] pp = new InfoEdits.Point[2];pp[0] = this.Points.Find(a => a.ID == ff[0]);pp[1] = this.Points.Find(a => a.ID == ff[1]);this.InflectionPoints = pp;//this.CurvePoints[0] = this.Points.Find(a => a.ID == ff[0]);//this.CurvePoints[1] = this.Points.Find(a => a.ID == ff[1]);}}/// <summary>/// 得到两点之间的航向角(弧度-3.14-3.14)/// </summary>/// <param name="LatA"></param>/// <param name="LatB"></param>/// <param name="LngA"></param>/// <param name="LngB"></param>/// <returns></returns>private double GetBear(double LatA, double LatB, double LngA, double LngB){double bear = 0.0;//double E = LngB - LngA;double N = LatB - LatA;bear = Math.Atan2(E, N);//得到弧度-3.14~3.14return bear;}}//public class TrackPiece//{// public int ID { get; set; }// public int TrackID { get; set; }// public int StartPointID { get; set; }// public int EndPointID { get; set; }// public double Bear { get; set; }// public double Length { get; set; }//}public class Balise{public int ID { get; set; }public double DeltaPos { get; set; }public double X { get; set; }public double Y { get; set; }public int TrackID { get; set; }public BaliseDirection Direction { get; set; } = BaliseDirection.temp;//预留public BaliseProperty Property { get; set; } = BaliseProperty.temp;public int Type { get; set; }public int VisioIndex { get; set; }}public class Topology{public string Name { get; set; }//拓扑名称public int ID { get; set; }//车站编号public string UpLinkStationName { get; set; }public string DownLinkStationName { get; set; }public Direction Direction { get; set; } = 0;//初始设置为纬度升序public List<Track> Tracks { get; set; }public List<Point> Points { get; set; }public List<Line> Lines { get; set; }public List<Balise> Balises { get; set; }public List<int> TrackID { get; set; }//正线IDpublic List<int> CrossLineID { get; set; }//渡线IDpublic List<int> SideID { get; set; }//侧线IDpublic double Scale { get; set; } = 100;//比例尺,默认设置100public Dictionary<int, InfoEdits.Point[]> Dic { get; set; } = new Dictionary<int, InfoEdits.Point[]>();//保存直线和正线的直线方程/// <summary>/// 更新Track上的点/// </summary>public void UpdateTrack(){List<InfoEdits.Point> points = this.Points;foreach (InfoEdits.Track t in this.Tracks){t.Points.ForEach(a => points.Find(b => b.ID == a.ID));t.Y = t.Points.First().Y;if (t.InflectionPoints != null){t.InflectionPoints = new InfoEdits.Point[2] { t.Points.Find(b => b.ID == t.inflectionPoints[0]), t.Points.Find(b => b.ID == t.inflectionPoints[1]) };t.Y = t.Points.Find(a => a.ID == t.inflectionPoints[0] + 1).Y;}}}public void UpdateLinearDic(){this.Dic.Clear();foreach(Track t in this.Tracks){if(t.Type==DeviceType.UpsideTrack||t.Type==DeviceType.DownsideTrack){Dic.Add(t.ID, new Point[2] { t.Points.First(), t.Points.Last() });}else if(t.Type==DeviceType.Side){if (!t.inflectionPoints.Contains(0)){Dic.Add(t.ID, t.InflectionPoints);}}}}}public enum DeviceType{PiecePoint=0,//轨道点StartPoint=1,//虚拟起点Signal=2,//信号机Switch=3,//道岔Crossline=4,//渡线SingleTrack=5,//轨道区段Side=6,//侧线EndPoint=7,//虚拟终点Balise=8,//应答器UpsideTrack=9,DownsideTrack=10}//按照正线的下行方向public enum Direction{LatAscend=0,//纬度升序,站型1LatDescend=1,//纬度降序,站型2LngAscend =2,//经度升序,站型3LngDesecnd =3,//经度降序,站型4}public enum SwitchDirection{Reverse=0,//岔尖所在轨道的位置偏移减小的方向(上行方向)Forward = 1,//岔尖所在轨道的位置偏移增长方向(下行方向)None=999//非道岔}public enum BaliseDirection{bothway=0,reverse=1,forward=2,temp=3}public enum BaliseProperty{VB=0,//Virtual BaliseEntity=1,//实体应答器VB_2=2,//有区间数据的虚拟应答器temp=3//预留}}
思路见:
语雀内容
#region 列控数据表绘图方法/// <summary>/// 从列控工程数据表Excel表出图/// </summary>/// <param name="selectedFiles"></param>private void DrawVisio(List<string> selectedFiles){List<TxtPoint> allPoints = new List<TxtPoint>();//利用循环遍历出key和value//选择的文件---现在暂时必须只能是列控数据Excel表中的foreach (string f in selectedFiles){allPoints.AddRange((List<TxtPoint>)Hashtable[f]);}double minkilo = allPoints.Min(a => a.KiloPos);//最小公里标---定x轴double maxkilo = allPoints.Max(a => a.KiloPos);//最大公里标//之后考虑是否在Excel转Txtpoint的时候就提取轨道编号//需要提取字符串中的数字int trackidmin = allPoints.Min(a => ExtractNumbersFormString(a.TrackName));//最小的轨道编号-定y轴int trackidmax = allPoints.Max(a => ExtractNumbersFormString(a.TrackName));//最大的轨道编号//分类别保存List<TxtPoint> joints = allPoints.Where(a => a.type == PointType.Joint).ToList();//绝缘节列表List<TxtPoint> signals = allPoints.Where(a => a.type == PointType.Signal).ToList();//信号机列表List<TxtPoint> ssignals = signals.Where(a => a.TypeName.Contains("S")).ToList();//上行信号机列表List<TxtPoint> xsignals = signals.Where(a => a.TypeName.Contains("X")).ToList();//下行信号机列表List<TxtPoint> switchs = allPoints.Where(a => a.type == PointType.Switch).ToList();//道岔列表double deltakilo = maxkilo - minkilo;//主要为了和Page的宽度设置比例尺int[] PosY = new int[] { 5, 6, 7, 8, 9, 10 };//直接定好根据轨道编号y坐标,索引值即轨道编号,即编号为1时y坐标为2//公里标作为x坐标//y坐标按照轨道编号来定Visio.Shape shape;//用轨道名称号重新分组var group = joints.GroupBy(a => ExtractNumbersFormString(a.TrackName)).ToList();foreach (IGrouping<int, TxtPoint> g in group){List<int> shapeIndex = new List<int>();//每个组都有一个新的指数值表List<TxtPoint> points = g.ToList();points = points.OrderBy(a => a.KiloPos).ToList();//根据公里标重新排序foreach (TxtPoint p in points){int trackid = ExtractNumbersFormString(p.TrackName);shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Joint"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid]);p.VisShapeIndex = shape.Index;//记住图形的index}for (int j = 0; j < points.Count - 1; j++)//连接每个shape{Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage;Shape BeginShape = visPage.Shapes[points[j].VisShapeIndex];Shape EndShape = visPage.Shapes[points[j + 1].VisShapeIndex];ConnectedShapes(BeginShape, EndShape);points[j].IsConnected = true;points[j + 1].IsConnected = true;}}//用一个字典保存每个轨道的两个点Dictionary<int, TxtPoint[]> dic = new Dictionary<int, TxtPoint[]>();foreach (IGrouping<int, TxtPoint> g in group){List<TxtPoint> points = g.ToList();if (points.Count >= 2){points = points.OrderBy(a => a.KiloPos).ToList();//根据公里标重新排序TxtPoint[] p2 = new TxtPoint[2] { points[0], points[1] };//选取前两个dic.Add(ExtractNumbersFormString(points[0].TrackName), p2);}}//设置信号机的位置//上行信号机在轨道的下方,所以y要减0.1左右//同时还要考虑X/S信号机foreach (TxtPoint p in ssignals){int trackid = ExtractNumbersFormString(p.TypeName);if (trackid == 0)//如果是S信号机{trackid = ReturnTrackId(p, dic);}shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Signal2.0"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid] - 0.2);shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*2";shape.Characters.Begin = 0;shape.Characters.End = 0;shape.Characters.Text = p.TypeName;p.VisShapeIndex = shape.Index;}foreach (TxtPoint p in xsignals){int trackid = ExtractNumbersFormString(p.TypeName);if (trackid == 0)//如果是X信号机{trackid = ReturnTrackId(p, dic);}shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Signal1.0"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid] + 0.2);//添加设备的名称/文本shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*2";shape.Characters.Begin = 0;shape.Characters.End = 0;shape.Characters.Text = p.TypeName;p.VisShapeIndex = shape.Index;}//先设置Switch的位置,根据每个轨道两个点的直线来设置道岔的位置,并且保存Index值List<int> switchIndex = new List<int>();//将道岔按照公里标大小排序switchs = switchs.OrderBy(a => a.KiloPos).ToList();//比如江仓站就是13957;foreach (TxtPoint p in switchs){int trackid = ReturnTrackId(p, dic);//通过比较道岔点与轨道直线的距离判定属于哪个轨道shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Switch"], (p.KiloPos - minkilo) / deltakilo * 15, PosY[trackid]);shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*5";shape.Characters.Begin = 0;shape.Characters.End = 0;shape.Characters.Text = p.TypeName;p.TrackName = trackid.ToString();p.VisShapeIndex = shape.Index;}//连接各个Switch,思路是按照公里标相近的道岔,判断是否是同一个轨道---其实这样是不对的//1-9,3-5for (int i = 0; i < switchs.Count; i++){if (!switchs[i].IsConnected)//如果图形没有连接过{Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage//当两个道岔轨道编号不等且时退出for (int j = i; j < switchs.Count; j++){int track1Id = Convert.ToInt32(switchs[i].TrackName);int track2Id = Convert.ToInt32(switchs[j].TrackName);int delta = Math.Abs(track1Id - track2Id);//跳过轨道名称相同的和跳过不是相邻轨道的(差1)if (delta == 0 || delta > 1){continue;}//跳过已经连接了的轨道if (switchs[j].IsConnected){continue;}else if (!switchs[j].IsConnected){Shape BeginShape = visPage.Shapes[switchs[i].VisShapeIndex];Shape EndShape = visPage.Shapes[switchs[j].VisShapeIndex];ConnectedShapes(BeginShape, EndShape);switchs[i].IsConnected = true;switchs[j].IsConnected = true;break;}}}else{break;}}}#endregion#region 电子地图xml文件绘制站场图private void DrawTopology(Station station){InfoEdits.Topology Topo = InitialTopoElements(station);//初始设置点线的连接关系SetTrackX(ref Topo);//设置正线的X坐标SetSwitchDirection(station, ref Topo);//设置道岔的开叉方向--以此为依据设置轨道的层数、Y坐标Topo.UpdateTrack();//更新轨道的点SetTrackY(ref Topo);//设置直股的Y坐标//SetTrackY2(ref Topo);//设置直股的Y坐标Topo.UpdateTrack();//更新Track中的点SetAllCrossLineXY(ref Topo);//设置渡线的坐标;//检查XY坐标CheckXY(Topo.Points);SetSideXY(ref Topo);//设置侧线的XY坐标Topo.UpdateTrack();//UpdateTrack(ref Topo);SetBalisePos(ref Topo);//设置应答器的逻辑坐标DrawTopology(ref Topo);CheckXY(Topo.Points);this.Topo = Topo;}/// <summary>/// 初步建立拓扑点线连接图,点的编号和前后向类型/// </summary>/// <param name="station"></param>private InfoEdits.Topology InitialTopoElements(Station station){//初次添加轨道、点、线InfoEdits.Topology topo = new InfoEdits.Topology();topo.Name = station.StationProperties.StationName;topo.UpLinkStationName = station.StationProperties.UplinkStationNum.ToString();topo.DownLinkStationName = station.StationProperties.DownlinkStationNum.ToString();List<InfoEdits.Track> tracks = new List<InfoEdits.Track>();List<InfoEdits.Point> Points = new List<InfoEdits.Point>();List<InfoEdits.Line> Lines = new List<InfoEdits.Line>();int index = 1;for (int i = 0; i < station.TrackInfo.Tracks.Count; i++){Track tc = station.TrackInfo.Tracks[i];InfoEdits.Track t = new InfoEdits.Track();List<int> trackids = new List<int>();List<int> CrosslineId = new List<int>();List<int> SideId = new List<int>();t.ID = tc.TrackID;if(tc.TrackType == 1){t.Type = InfoEdits.DeviceType.SingleTrack;trackids.Add(t.ID);}else if(tc.TrackType==2){t.Type = InfoEdits.DeviceType.UpsideTrack;trackids.Add(t.ID);}else if (tc.TrackType == 3){t.Type = InfoEdits.DeviceType.DownsideTrack;//正线轨道trackids.Add(t.ID);}else if(tc.TrackType==4){t.Type = InfoEdits.DeviceType.Side;//侧线SideId.Add(t.ID);}else if(tc.TrackType==5){t.Type = InfoEdits.DeviceType.Crossline;//渡线CrosslineId.Add(t.ID);}topo.TrackID = trackids;topo.SideID = SideId;topo.CrossLineID = CrosslineId;double startlat = tc.StartLat;double startlon = tc.StartLon;List<InfoEdits.Point> points = new List<InfoEdits.Point>();List<InfoEdits.Line> lines = new List<InfoEdits.Line>();if (tc.TrackType == 4 || tc.TrackType == 5)//如果是侧线或者是渡线,第一个point设置为Switch{//暂时ReverseID设置为0int indexx = index;InfoEdits.Point pp;for (int j = 0; j < station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces.Count; j++){TrackPiece tp = station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces[j];if (j == 0)//是第一个点{pp=new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.Switch);points.Add(pp);}else{pp = new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.PiecePoint);points.Add(pp);}index++;}pp = new InfoEdits.Point(tc.EndLat / 3600000.0, tc.EndLon / 3600000.0, index, t.ID, InfoEdits.DeviceType.Switch, 0, index + 1);points.Add(pp);index++;for (int j=indexx;j<index-1;j++){lines.Add(new InfoEdits.Line(indexx, points.Find(a=>a.ID==indexx), points.Find(a => a.ID == indexx+1)));}}else //如果是正线类型,设置起始点为StartPoint{int indexx = index;InfoEdits.Point pp;for (int j = 0; j < station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces.Count; j++){TrackPiece tp = station.TrackInfo.TrackGIS.TrackPieceGIS[i].TrackPieces[j];if (j == 0)//是第一个点{pp = new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.StartPoint);points.Add(pp);}else{pp = new InfoEdits.Point((tp.DeltaLat + startlat) / 3600000.0, (tp.DeltaLon + startlon) / 3600000.0, index, t.ID, InfoEdits.DeviceType.PiecePoint);points.Add(pp);}index++;}pp = new InfoEdits.Point(tc.EndLat / 3600000.0, tc.EndLon / 3600000.0, index, t.ID, InfoEdits.DeviceType.EndPoint);points.Add(pp);index++;for (int j = indexx; j < index - 1; j++){lines.Add(new InfoEdits.Line(indexx, points.Find(a => a.ID == indexx), points.Find(a => a.ID == indexx + 1)));}}t.Points = points;t.Lines = lines;tracks.Add(t);Points.AddRange(points);Lines.AddRange(lines);}topo.Tracks = tracks;topo.Points = Points;topo.Lines = Lines;if(tracks.First().StartX<tracks.Last().StartX){topo.Direction = InfoEdits.Direction.LatAscend;}else{topo.Direction = InfoEdits.Direction.LatDescend;}topo.UpdateTrack();foreach(InfoEdits.Track t in topo.Tracks){t.SetInflectionPoints();//如果是侧线设置拐点}//设置道岔点的前向后向和侧向ID//拓扑更新直线方程topo.UpdateLinearDic();var switchTracks = station.TrackInfo.Tracks.Where(a => a.TrackType > 3);//侧线和渡线foreach (Track t in switchTracks){var tt = tracks.Find(a => a.ID == t.TrackID);SetSwitchPoint(ref tt, tracks,topo.Dic);}//检查--发现拓扑仍然不对Check(topo);//判断两个点之间是否有多余插入的点,重新排序。//注意不仅点要排序,其实Line也要排序,其实line有重叠部分,在拓扑点安排好之前不应生成Line的编号foreach(Track t in station.TrackInfo.Tracks){if(t.TrackType<=3){var group = topo.Points.GroupBy(a => a.TrackID == t.TrackID);foreach (IGrouping<bool, InfoEdits.Point> g in group){if (g.Key == true){//直股编号上的所有点集合,重新排列前后顺序List<InfoEdits.Point> points = (List<InfoEdits.Point>)g.ToList();//首先根据纬度方向排序//如果拓扑正线的方向是纬度升序if (topo.Direction == InfoEdits.Direction.LatAscend|| topo.Direction == InfoEdits.Direction.LngDesecnd){points = points.OrderBy(a => a.Lat).ToList();for (int j = 0; j < points.Count; j++){if (points[j].pointType == InfoEdits.DeviceType.StartPoint){points[j].ForwardID = points[j + 1].ID;}else if (points[j].pointType == InfoEdits.DeviceType.EndPoint){points[j].ReverseID = points[j - 1].ID;}else{points[j].ReverseID = points[j - 1].ID;points[j].ForwardID = points[j + 1].ID;}}}//如果拓扑的方向是纬度降序else if (topo.Direction == InfoEdits.Direction.LatDescend || topo.Direction == InfoEdits.Direction.LngAscend){points = points.OrderByDescending(a => a.Lat).ToList();for (int j = 0; j < points.Count; j++){if (points[j].pointType == InfoEdits.DeviceType.StartPoint){points[j].ForwardID = points[j + 1].ID;}else if (points[j].pointType == InfoEdits.DeviceType.EndPoint){points[j].ReverseID = points[j - 1].ID;}else{points[j].ReverseID = points[j - 1].ID;points[j].ForwardID = points[j + 1].ID;}}}}}}}topo.Balises = GetBalises(station);//检查基本正确return topo;}private List<InfoEdits.Balise> GetBalises(Station station){List<Balise> balises = station.TrainControlData.BaliseData.Balises;List<InfoEdits.Balise> bs = new List<InfoEdits.Balise>();foreach(Balise b in balises){InfoEdits.Balise b_2 = new InfoEdits.Balise();b_2.ID = balises.IndexOf(b) + 1;b_2.TrackID = b.BaliseTrackNum;b_2.DeltaPos = b.BalisePos;int direction = b.BaliseProperty & 192;b_2.Direction = (InfoEdits.BaliseDirection)direction;int prop = b.BaliseProperty & 3;b_2.Property = (InfoEdits.BaliseProperty)prop;b_2.Type = b.BaliseLoc;bs.Add(b_2);}return bs;}/// <summary>/// 更新Track上的点/// </summary>/// <param name="topo"></param>private void UpdateTrack(ref InfoEdits.Topology topo){List<InfoEdits.Point> points = topo.Points;foreach(InfoEdits.Track t in topo.Tracks){t.Points.ForEach(a => points.Find(b => b.ID == a.ID));}}private string Check(InfoEdits.Topology topo){string s = "";foreach (InfoEdits.Track t in topo.Tracks){s += t.ID.ToString() + "\r\n";foreach (InfoEdits.Point p in t.Points){s += string.Format("编号{0},前向点{1},后向点{2},侧边点{3},直股编号{4},弯股编号{5}", p.ID, p.ReverseID, p.ForwardID, p.SideID, p.TrackID, p.Track2ID) + "\r\n";}}Console.WriteLine(s);return s;}private string Check(List<InfoEdits.Point> points){string s = "";foreach (InfoEdits.Point p in points){s += string.Format("编号{0},前向点{1},后向点{2},侧边点{3},直股编号{4},弯股编号{5}", p.ID, p.ReverseID, p.ForwardID, p.SideID, p.TrackID, p.Track2ID) + "\r\n";}Console.WriteLine(s);return s;}/// <summary>/// 检查点/// </summary>/// <param name="points"></param>/// <returns></returns>private string Check2(List<InfoEdits.Point> points){string s = "";foreach (InfoEdits.Point p in points){s += string.Format("编号{0},道岔方向{1},点类型{2},备注{3}",p.ID, p.SwitchDirection,p.pointType.ToString(),p.Tag) + "\r\n";}Console.WriteLine(s);return s;}///// <summary>///// 设置道岔点的前后向节点指针///// </summary>///// <param name="track"></param>///// <param name="tracks"></param>///// <param name="dic"></param>//private void SetSwitchPoint(ref InfoEdits.Track track,List<InfoEdits.Track> tracks,Dictionary<int,InfoEdits.Point[]> dic)//{// int tracknum = track.ID;//所处轨道的编号// var startPoint = track.Points.First();// var endPoint = track.Points.Last();// if (startPoint.pointType == InfoEdits.DeviceType.Switch)// {// int trackID = ReturnTrackId(startPoint, dic);//dic中只保存正线直线方程// InfoEdits.Track t = tracks.Find(a => a.ID == trackID);// int[] ids = ReturnClosedID(startPoint, t.Points);// startPoint.SideID = track.Points[1].ID;// //dictionary保存的正线直线一定在道岔的两端,所以暂时不判断// startPoint.ReverseID = ids[0];// startPoint.ForwardID = ids[1];// startPoint.TrackID = trackID;//直股ID// }// if (endPoint.pointType == InfoEdits.DeviceType.Switch)// {// int trackID = ReturnTrackId(endPoint, dic);//dic中只保存正线直线方程// InfoEdits.Track t = tracks.Find(a => a.ID == trackID);// int[] ids = ReturnClosedID(endPoint, t.Points);// endPoint.SideID = track.Points.Last().ID - 1;//倒数第二个点的ID// endPoint.ReverseID = ids[0];// endPoint.ForwardID = ids[1];// endPoint.TrackID = trackID;//直股ID// }//}/// <summary>/// 设置道岔点的前后向节点指针/// </summary>/// <param name="track"></param>/// <param name="tracks"></param>/// <param name="dic"></param>private void SetSwitchPoint(ref InfoEdits.Track track, List<InfoEdits.Track> tracks, Dictionary<int, InfoEdits.Point[]> dic){int tracknum = track.ID;//所处轨道的编号var startPoint = track.Points.First();var endPoint = track.Points.Last();if (startPoint.pointType == InfoEdits.DeviceType.Switch){int trackID = ReturnTrackId(startPoint, dic);//dic中只保存正线直线方程startPoint.SideID = track.Points[1].ID;//dictionary保存的正线直线一定在道岔的两端,所以暂时不判断startPoint.TrackID = trackID;//直股ID}if (endPoint.pointType == InfoEdits.DeviceType.Switch){int trackID = ReturnTrackId(endPoint, dic);//dic中只保存正线直线方程endPoint.SideID = track.Points.Last().ID - 1;//倒数第二个点的IDendPoint.TrackID = trackID;//直股ID}}/// <summary>/// 根据xml文件中的道岔设置相应的道岔点的开岔方向/// </summary>/// <param name="station"></param>/// <param name="Topo"></param>private void SetSwitchDirection(Station station,ref InfoEdits.Topology Topo){var switchPoints = Topo.Points.Where(a=>a.pointType==InfoEdits.DeviceType.Switch).ToList();List<Switch> switches = station.TrainControlData.SwitchData.Switches;foreach(InfoEdits.Point p in switchPoints){var switchs = switches.Where(a => a.SwitchPosTrackNum == p.TrackID&&a.SwitchReverseTrackNum == p.Track2ID);foreach(Switch s in switchs){if(Math.Abs(s.SwitchPos-p.X*10000)<=300)//阈值300cm-3m{p.Tag = "SW" + s.SwitchNum.ToString();p.SwitchDirection = (InfoEdits.SwitchDirection)s.SwitchDirection;}}}//捡漏var swip = switchPoints.FindAll(a => a.SwitchDirection == InfoEdits.SwitchDirection.None);foreach(InfoEdits.Point p in swip){var switchs = switches.Where(a => a.SwitchPosTrackNum == p.TrackID && a.SwitchReverseTrackNum == p.Track2ID);foreach (Switch s in switchs){if (Math.Round(s.SwitchPos/10000 - p.X,0) == -1)//阈值300cm-3m{p.Tag = "SW" + s.SwitchNum.ToString();p.SwitchDirection = (InfoEdits.SwitchDirection)s.SwitchDirection;}}}Check2(switchPoints);}/// <summary>/// 返回中心点与点集合距离的最小点,此方法针对已经确定centerP点处于正线的中间/// </summary>/// <param name="centerP">中心点</param>/// <param name="points">要比较的点集</param>/// <returns></returns>private int[] ReturnClosedID(InfoEdits.Point centerP,List<InfoEdits.Point> points){int[] ids = new int[2];//points = points.OrderBy(a => a.Lat).ToList();//根据纬度排序points = points.Where(a => a != centerP).ToList();//排除本身Dictionary<int,double> dic = new Dictionary<int, double>();List<double> distance = new List<double>();foreach(InfoEdits.Point p in points){double dis = GetDistance(centerP.Lat, centerP.Lon, p.Lat, p.Lon);distance.Add(dis);dic.Add(p.ID, dis);}distance =distance.OrderBy(a=>a).ToList();//按照距离升序排序。var key1 = dic.Where(q => q.Value == distance[0]).Select(a => a.Key).ToList<int>();var key2 = dic.Where(q => q.Value == distance[1]).Select(a => a.Key).ToList<int>();if(key1[0]<key2[0]){ids[0] = key1[0];ids[1] = key2[0];}else if(key1[0]>key2[0]){ids[0] = key2[0];ids[1] = key1[0];}return ids;}/// <summary>/// 根据直股上两点的距离设置相对位置X坐标/// </summary>/// <param name="topo"></param>private void SetTrackX(ref InfoEdits.Topology topo){//设置Y坐标,先找到正线foreach (InfoEdits.Track t in topo.Tracks.FindAll(a => a.Type == InfoEdits.DeviceType.SingleTrack||a.Type==InfoEdits.DeviceType.DownsideTrack||a.Type==InfoEdits.DeviceType.UpsideTrack)){var points = topo.Points.FindAll(a => a.TrackID == t.ID);//设置正线的x坐标;double lat = 0.0;double lng = 0.0;if (topo.Direction == InfoEdits.Direction.LatDescend){points = points.OrderByDescending(a => a.Lat).ToList();lat = points.First().Lat;lng = points.First().Lon;}else if (topo.Direction == InfoEdits.Direction.LatAscend){points = points.OrderBy(a => a.Lat).ToList();lat = points.First().Lat;lng = points.First().Lon;}foreach (InfoEdits.Point p in points){double length = GetDistance(lat, lng, p.Lat, p.Lon);//p.X = length / 100;p.X = length / topo.Scale;}}}/// <summary>/// 根据道岔的开岔方向设置直股的Y坐标/// </summary>/// <param name="topo"></param>private void SetTrackY(ref InfoEdits.Topology topo){List<InfoEdits.Point> points = new List<InfoEdits.Point>();List<InfoEdits.Point> switchs = new List<InfoEdits.Point>();double[] PosY = new double[topo.Tracks.Count];if (topo.Direction == InfoEdits.Direction.LatAscend)//纬度升序{switchs =topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderBy(a => a.Lat).ToList();}else if (topo.Direction == InfoEdits.Direction.LatDescend)//纬度降序{switchs = topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderByDescending(a => a.Lat).ToList();}PosY[0] = 5;//设置图纸上正线的Y坐标为5//遍历正线和侧线轨道//找到同属于一个所有道岔点,其中包括了弯轨是侧线或者渡线的道岔点foreach (InfoEdits.Point p in switchs){if (p.SwitchDirection == InfoEdits.SwitchDirection.Forward)//下行方向{//如果道岔点连接的是侧线,即单动道岔InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));if (tc.Type == InfoEdits.DeviceType.Side){if (PosY[p.TrackID - 1] != 0 && PosY[p.Track2ID - 1] == 0)//(PosY[t.ID - 1]!=0){PosY[p.Track2ID - 1] = PosY[p.TrackID - 1] - 1;//PosY[t.ID - 1] - 1;//Y坐标-1}}//如果道岔点连接的是渡线else if (tc.Type == InfoEdits.DeviceType.Crossline){int nextid = tc.Points.Last().TrackID;//渡线最后一个点if (PosY[p.TrackID - 1] != 0&& PosY[nextid - 1]==0)//(PosY[t.ID - 1] != 0){PosY[nextid - 1] = PosY[p.TrackID - 1] - 1;//PosY[t.ID - 1] - 1;//Y坐标-1}}}else if (p.SwitchDirection == InfoEdits.SwitchDirection.Reverse)//上行方向{//如果道岔点连接的是侧线,即单动道岔InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));if (tc.Type == InfoEdits.DeviceType.Side){if (PosY[p.TrackID - 1] != 0&& PosY[p.Track2ID - 1]==0) //(PosY[t.ID - 1] != 0){PosY[p.Track2ID - 1] = PosY[p.TrackID - 1] + 1;//PosY[t.ID - 1] + 1;//Y坐标-1}}//如果道岔点连接的是渡线else if (tc.Type == InfoEdits.DeviceType.Crossline){int nextid = tc.Points.Last().TrackID;if (PosY[p.TrackID - 1] != 0&&PosY[nextid - 1] == 0)//(PosY[t.ID - 1] != 0){PosY[nextid - 1] = PosY[p.TrackID - 1] + 1;//PosY[t.ID - 1] + 1;//Y坐标+1}}}}foreach(double a in PosY){int index = PosY.FindIndex(i=>i==a);var track = topo.Tracks.Find(i => i.ID == index + 1);track.Y = a;}//设置了正线和侧线直股的坐标即道岔点的Y坐标foreach (InfoEdits.Track a in topo.Tracks){if(a.Type == InfoEdits.DeviceType.SingleTrack || a.Type == InfoEdits.DeviceType.DownsideTrack || a.Type == InfoEdits.DeviceType.UpsideTrack){var pps = topo.Points.FindAll(b => b.TrackID == a.ID);foreach(InfoEdits.Point p in pps){p.Y = PosY[a.ID - 1];}}else if(a.Type==InfoEdits.DeviceType.Side){var pps = topo.Points.FindAll(b => b.Track2ID == a.ID&&b.TrackID==b.Track2ID);foreach (InfoEdits.Point p in pps){p.Y = PosY[a.ID - 1];}}}CheckXY(topo.Points);}/// <summary>/// 根据道岔的开岔方向设置直股的Y坐标/// </summary>/// <param name="topo"></param>private void SetTrackY2(ref InfoEdits.Topology topo){List<InfoEdits.Point> points = new List<InfoEdits.Point>();List<InfoEdits.Point> switchs = new List<InfoEdits.Point>();double[] PosY = new double[topo.Tracks.Count];if (topo.Direction == InfoEdits.Direction.LatAscend)//纬度升序{switchs = topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderBy(a => a.Lat).ToList();}else if (topo.Direction == InfoEdits.Direction.LatDescend)//纬度降序{switchs = topo.Points.FindAll(a => a.pointType == InfoEdits.DeviceType.Switch).OrderByDescending(a => a.Lat).ToList();}PosY[0] = 5;//设置图纸上正线的Y坐标为5//遍历正线和侧线轨道//找到同属于一个所有道岔点,其中包括了弯轨是侧线或者渡线的道岔点foreach (InfoEdits.Point p in switchs){int track1id = p.TrackID;//直股idInfoEdits.Point[] track1points = topo.Dic[track1id];double angle1 = GetBear2(track1points[0].Lat, track1points[1].Lat, track1points[0].Lon, track1points[0].Lon);InfoEdits.Point forwardPoint = topo.Points.Find(a => a.ID == p.SideID);if (forwardPoint.ID < p.ID)//如果p点的侧边点编号比自己小,即p是股道的最后一个点,停止计算{continue;}double angle2 = GetBear2(p.Lat, forwardPoint.Lat, p.Lon, forwardPoint.Lon);double delta = angle2 - angle1;//夹角if (delta < 0){InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));if(tc.Type==InfoEdits.DeviceType.Side){int track2id = p.Track2ID;PosY[track2id - 1] = PosY[track1id - 1] + 1;}else{int track2id = tc.Points.Last().TrackID;PosY[track2id - 1] = PosY[track1id - 1] + 1;}}else if (delta > 0){InfoEdits.Track tc = topo.Tracks.Find(a => a.Points.Contains(p));if (tc.Type == InfoEdits.DeviceType.Side){int track2id = p.Track2ID;PosY[track2id - 1] = PosY[track1id - 1] - 1;}else{int track2id = tc.Points.Last().TrackID;PosY[track2id - 1] = PosY[track1id - 1] - 1;}}}foreach (double a in PosY){int index = PosY.FindIndex(i => i == a);var track = topo.Tracks.Find(i => i.ID == index + 1);track.Y = a;}//设置了正线和侧线直股的坐标即道岔点的Y坐标foreach (InfoEdits.Track a in topo.Tracks){if (a.Type == InfoEdits.DeviceType.SingleTrack || a.Type == InfoEdits.DeviceType.DownsideTrack || a.Type == InfoEdits.DeviceType.UpsideTrack){var pps = topo.Points.FindAll(b => b.TrackID == a.ID);foreach (InfoEdits.Point p in pps){p.Y = PosY[a.ID - 1];}}else if (a.Type == InfoEdits.DeviceType.Side){var pps = topo.Points.FindAll(b => b.Track2ID == a.ID && b.TrackID == b.Track2ID);foreach (InfoEdits.Point p in pps){p.Y = PosY[a.ID - 1];}}}CheckXY(topo.Points);}private void SetAllCrossLineXY(ref InfoEdits.Topology Topo){var tracks = Topo.Tracks.FindAll(a => a.Type == InfoEdits.DeviceType.Crossline);foreach(InfoEdits.Track t in tracks){InfoEdits.Point[] PointAB = new InfoEdits.Point[2] { t.Points.First(), t.Points.Last() };for (int i = 1; i < t.Points.Count - 1; i++){var PointC = Topo.Points.Find(a=>a.ID==t.Points[i].ID);double[] xy = PointBetweenPoints(PointC, PointAB);PointC.X = xy[0];PointC.Y = xy[1];}}}/// <summary>/// 主要用来计算斜线上点的XY坐标/// </summary>/// <param name="PointC"></param>/// <param name="Points">[0]-PointA;[1]-PointB</param>/// <returns></returns>private double[] PointBetweenPoints(InfoEdits.Point PointC,InfoEdits.Point[] Points){double[] xy = new double[2];InfoEdits.Point PointA = Points[0];InfoEdits.Point PointB = Points[1];double deltay = PointB.Y - PointA.Y;double deltax = PointB.X - PointA.X;double lengthAB = Math.Abs(GetDistance(PointA.Lat, PointA.Lon, PointB.Lat, PointB.Lon));double lengthAC = Math.Abs(GetDistance(PointA.Lat, PointA.Lon, PointC.Lat, PointC.Lon));xy[0] = lengthAC / lengthAB * deltax + PointA.X;xy[1] = lengthAC / lengthAB * deltay + PointA.Y;return xy;}//侧线上的所有Y已经设置好了/// <summary>/// 设置拓扑的侧线的所有点的坐标/// </summary>/// <param name="topo"></param>private void SetSideXY(ref InfoEdits.Topology topo){var side = topo.Tracks.FindAll(a => a.Type == InfoEdits.DeviceType.Side);foreach (InfoEdits.Track t in side){//获取侧线的两个折点int[] curvedPoints = ReturnCurvedPoints(t.Points);InfoEdits.Point A = t.Points.First();InfoEdits.Point B = t.Points.Last();//总长double all = GetDistance(A.Lat, A.Lon, B.Lat, B.Lon);double allxy = B.X - A.X;var curvePoint1 = topo.Points.Find(a => a.ID == curvedPoints[0]);var curvePoint2 = topo.Points.Find(a => a.ID == curvedPoints[1]);//首先设置折点curvePoint1和curvePoint2的X坐标//计算弧度double d = GetDistance(A.Lat, A.Lon, curvePoint1.Lat, curvePoint1.Lon);double angle = Math.Asin(GetPoint2Line(A, B, curvePoint1) / d);curvePoint1.X = d * Math.Cos(angle)/topo.Scale+A.X;d= GetDistance(B.Lat, B.Lon, curvePoint2.Lat, curvePoint2.Lon);angle = Math.Asin(GetPoint2Line(A, B, curvePoint2) / d);curvePoint2.X = B.X - d * Math.Cos(angle) / topo.Scale;//分成三段处理for (int j = 1; j < t.Points.IndexOf(curvePoint1); j++){double[] PosXY = PointBetweenPoints(t.Points[j], new InfoEdits.Point[2] { A, curvePoint1 });var point = topo.Points.Find(a => a.ID == t.Points[j].ID);point.X = PosXY[0];point.Y = PosXY[1];}//直股段double dis = GetDistance(curvePoint1.Lat, curvePoint1.Lon, curvePoint2.Lat, curvePoint2.Lon);double dx = curvePoint2.Y - curvePoint1.X;for (int a = t.Points.IndexOf(curvePoint1) + 1; a < t.Points.IndexOf(curvePoint2); a++){InfoEdits.Point PointA = t.Points[a - 1];InfoEdits.Point PointB = t.Points[a];double l = GetDistance(PointA.Lat, PointA.Lon, PointB.Lat, PointB.Lon);var point = topo.Points.Find(b => b.ID == t.Points[a].ID);//point.X = curvePoint1.X + l / dis * dx;point.X = curvePoint1.X + l / Topo.Scale;}for (int b = t.Points.IndexOf(curvePoint2) + 1; b < t.Points.Count(); b++){double[] PosXY = PointBetweenPoints(t.Points[b], new InfoEdits.Point[2] { curvePoint2, B });var point = topo.Points.Find(a => a.ID == t.Points[b].ID);point.X = PosXY[0];point.Y = PosXY[1];}}}private void SetBalisePos(ref InfoEdits.Topology topo){foreach(InfoEdits.Balise b in topo.Balises){var t = topo.Tracks.Find(a => a.ID == b.TrackID);double startx = t.Points.First().X;double y = t.Y;if (t.Type==InfoEdits.DeviceType.UpsideTrack|| t.Type == InfoEdits.DeviceType.DownsideTrack|| t.Type == InfoEdits.DeviceType.SingleTrack){b.X = startx + b.DeltaPos / 100 / topo.Scale;b.Y = y - 0.1;}else if(t.Type==InfoEdits.DeviceType.Side){InfoEdits.Point inflectionPoint1 = t.InflectionPoints[0];var basex = topo.Tracks.Find(a => a.Type == InfoEdits.DeviceType.DownsideTrack).Points.First().X;b.X = b.DeltaPos/100/topo.Scale+basex;b.Y = y - 0.1;}}}/// <summary>/// 绘制已经编制好的Topo至Visio图纸/// </summary>/// <param name="topo"></param>private void DrawTopology(ref InfoEdits.Topology topo){SetPointPos(ref topo);//设置所有点(未包括信号机、应答器)ConnectAllPoints(topo);SetOthersShape(topo);//设置下行方向,上行车站、下行车站等形状//SetBalisePos(ref topo);SetBaliseShape(ref topo);}private void ConnectAllPoints(InfoEdits.Topology topo){foreach (InfoEdits.Track t in topo.Tracks){if (t.Type == InfoEdits.DeviceType.SingleTrack || t.Type == InfoEdits.DeviceType.DownsideTrack || t.Type == InfoEdits.DeviceType.UpsideTrack){var points = topo.Points.FindAll(a => a.TrackID == t.ID);ConnectPoints(points);}else{var points = topo.Points.FindAll(a => a.Track2ID == t.ID);ConnectPoints(points);}}}/// <summary>/// 遍历拓扑中的所有点并设置XY坐标,记录point的VisioIndex/// </summary>/// <param name="topo"></param>private void SetPointPos(ref InfoEdits.Topology topo){Shape shape;foreach (InfoEdits.Point p in topo.Points){shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Joint"], p.X, p.Y);p.VisioIndex = shape.Index;//记住图形的indexshape.Characters.Begin = 0;shape.Characters.End = 0;if (string.IsNullOrEmpty(p.Tag)){shape.Characters.Text = p.ID.ToString();}else{shape.Characters.Text = p.Tag;}shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,(short)VisRowIndices.visRowTextXForm, 6).FormulaU = "90 deg";shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,(short)VisRowIndices.visRowTextXForm, 2).FormulaU = "Width*10";shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,(short)VisRowIndices.visRowTextXForm, 0).FormulaU = "Width*-0.8";}}/// <summary>/// 连接两个Visio绝缘节对象/// </summary>/// <param name="points"></param>private void ConnectPoints(List<InfoEdits.Point> points){for (int j = 0; j < points.Count - 1; j++){Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage;Shape BeginShape = visPage.Shapes[points[j].VisioIndex];Shape EndShape = visPage.Shapes[points[j + 1].VisioIndex];ConnectedShapes(BeginShape, EndShape);points[j].IsConnected = true;points[j + 1].IsConnected = true;}}private void SetBaliseShape(ref InfoEdits.Topology topo){Shape shape;foreach(InfoEdits.Balise b in topo.Balises){string shapename = string.Format("Balise{0}", b.Type);shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters[shapename],b.X, b.Y);b.VisioIndex = shape.Index;}}private void SetOthersShape(InfoEdits.Topology topo){double minx = topo.Points.Min(a => a.X);double maxx = topo.Points.Max(a => a.X);double maxy = topo.Points.Max(a => a.Y);double width = 2;double height = 0.4;double deltay = 2;//Y坐标偏移double deltax = 0.8;//添加下行方向标志Shape shape;shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Direction"], (minx+maxx)/2, maxy+1);shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,(short)VisRowIndices.visRowXForm1D, 2).FormulaU = "334.30000280175 mm";shape.get_CellsSRC((short)VisSectionIndices.visSectionObject,(short)VisRowIndices.visRowXForm1D, 3).FormulaU = "177.00000147154 mm";shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowLine, 0).FormulaU = "2 pt";shape.Characters.CharProps[7] = 30;//添加车站文本,设置无外框线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);shape.TextStyle = "Normal";shape.LineStyle = "Text Only";shape.FillStyle = "Text Only";shape.Characters.Begin = 0;shape.Characters.End = 0;shape.Characters.Text = topo.Name;shape.get_CellsSRC((short)VisSectionIndices.visSectionCharacter, 0, 7).FormulaU = "30 pt";shape.get_CellsSRC((short)VisSectionIndices.visSectionCharacter, 0, 2).FormulaU = "17";shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowLine, 2).FormulaU = "0";shape.get_CellsSRC((short)VisSectionIndices.visSectionObject, (short)VisRowIndices.visRowGradientProperties, 4).FormulaU = "FALSE";}/// <summary>/// 得到两点之间的航向角(弧度-3.14-3.14)/// </summary>/// <param name="LatA"></param>/// <param name="LatB"></param>/// <param name="LngA"></param>/// <param name="LngB"></param>/// <returns></returns>private double GetBear(double LatA, double LatB, double LngA, double LngB){double bear = 0.0;//double E = LngB - LngA;double N = LatB - LatA;bear = Math.Atan2(E, N);//得到弧度-3.14~3.14return bear;}/// <summary>/// 找到侧线轨道的两个弯轨点/// </summary>/// <param name="Points"></param>/// <returns></returns>private int[] ReturnCurvedPoints(List<InfoEdits.Point> Points){int[] flags = new int[2];List<int> ff = new List<int>();double temp = 0.0;int tempid = 0;for (int i = 1; i < Points.Count; i++){double bear = GetBear(Points[i - 1].Lat, Points[i].Lat, Points[i - 1].Lon, Points[i].Lon);Console.WriteLine(bear.ToString());if (i == 1 ){temp = bear;tempid = Points[i].ID;}else if (Math.Abs(bear - temp) < 0.0174533)//设置阈值为1度{temp = bear;}else if (Math.Abs(bear - temp) > 0.0174533)//1度{temp = bear;tempid = Points[i - 1].ID;ff.Add(tempid);}Console.WriteLine(Math.Abs(bear - temp).ToString());}ff.Sort();flags[0] = ff[0];flags[1] = ff[1];Console.WriteLine(flags[0].ToString()+","+flags[1].ToString());return flags;}/// <summary>/// 检查点坐标/// </summary>/// <param name="points"></param>private void CheckXY(List<InfoEdits.Point> points){string s = "";foreach(InfoEdits.Point p in points){s += string.Format("ID{0},X坐标{1},Y坐标{2}",p.ID, p.X, p.Y) + "\r\n";}Console.WriteLine(s);}private void DrawTopo(InfoEdits.Topology topo){foreach(InfoEdits.Track t in topo.Tracks){var points = topo.Points.FindAll(a => a.TrackID == t.ID);if(t.Type == InfoEdits.DeviceType.SingleTrack || t.Type == InfoEdits.DeviceType.DownsideTrack || t.Type == InfoEdits.DeviceType.UpsideTrack){double lat = 0.0;double lng = 0.0;if(topo.Direction==InfoEdits.Direction.LatDescend){points = points.OrderByDescending(a => a.Lat).ToList();lat = points.First().Lat;lng = points.First().Lon;}else if(topo.Direction == InfoEdits.Direction.LatAscend){points = points.OrderBy(a => a.Lat).ToList();lat = points.First().Lat;lng = points.First().Lon;}Shape shape;foreach (InfoEdits.Point p in points){double length = GetDistance(lat, lng, p.Lat, p.Lon);p.X = length / 100;p.Y = p.TrackID;shape = axDrawingControl1.Document.Pages[1].Drop(currentStencil.Masters["Joint"], p.X, p.Y);p.VisioIndex = shape.Index;//记住图形的index}for (int j = 0; j < points.Count - 1; j++)//连接每个shape{Visio.Page visPage = axDrawingControl1.Document.Pages[1];//ActivePage;Shape BeginShape = visPage.Shapes[points[j].VisioIndex];Shape EndShape = visPage.Shapes[points[j + 1].VisioIndex];ConnectedShapes(BeginShape, EndShape);BeginShape.Characters.Begin = 0;BeginShape.Characters.End = 0;BeginShape.Characters.Text = points[j].ID.ToString();EndShape.Characters.Begin = 0;EndShape.Characters.End = 0;EndShape.Characters.Text = points[j + 1].ID.ToString();points[j].IsConnected = true;points[j + 1].IsConnected = true;}}}}/// <summary>/// 以中心点旋转Angle角度/// </summary>/// <param name="center">中心点</param>/// <param name="p1">待旋转的点</param>/// <param name="angle">旋转角度(弧度)</param>private void PointRotate(Point center, ref Point p1, double angle){double x1 = (p1.X - center.X) * Math.Cos(angle) + (p1.Y - center.Y) * Math.Sin(angle) + center.X;double y1 = -(p1.X - center.X) * Math.Sin(angle) + (p1.Y - center.Y) * Math.Cos(angle) + center.Y;p1.X = (int)x1;p1.Y = (int)y1;}/// <summary>/// 以中心点旋转Angle角度/// </summary>/// <param name="centerX"></param>/// <param name="centerY"></param>/// <param name="pointX"></param>/// <param name="pointY"></param>/// <param name="angle"></param>private void PointRotate(double centerX,double centerY,ref double pointX,ref double pointY, double angle){double x1 = (pointX - centerX) * Math.Cos(angle) + (pointY - centerY) * Math.Sin(angle) + centerX;double y1 = -(pointX - centerX) * Math.Sin(angle) + (pointY - centerY) * Math.Cos(angle) + centerY;pointX = x1;pointY = y1;}private double GetBear2(double LatA, double LatB, double LngA, double LngB){double bear = 0.0;//double E = LngB - LngA;double N = LatB - LatA;bear = Math.Atan2(E, N);//得到弧度-3.14~3.14if (bear < 0){bear += 6.28;//弧度范围0~6.28}//改成角度//bear=headingA*180/Math.PI;//if(bear<0)//{// bear += 360;////}////方位角转换转弧度//bear *= 0.0174533;//if(bear>3.14)//{// bear -= 6.28;//}return bear;}public int ExtractNumbersFormString(string s){//取出字符串中所有的英文字母string strSplit1 = Regex.Replace(s, "[a-z]", "", RegexOptions.IgnoreCase);////取出字符串中所有的数字//string strSplit2 = Regex.Replace(FlightNO, "[0-9]", "", RegexOptions.IgnoreCase);if (string.IsNullOrEmpty(strSplit1))//避免S/X这种情况,{return 0;}else{return Convert.ToInt32(strSplit1);}}/// <summary>/// 连接绝缘节/// </summary>/// <param name="BeginShape"></param>/// <param name="EndShape"></param>private void ConnectedShapes(Shape BeginShape,Shape EndShape){Visio.Cell BeginXCell;Visio.Cell EndXCell;//用来确定连接线连在图形的上下左右,不同图形值不一样Page visPage = axDrawingControl1.Document.Pages[1];Shape connector = visPage.Drop(visApp.ConnectorToolDataObject, 1.2386, 3.2458);BeginXCell = connector.get_CellsU("BeginX");EndXCell = BeginShape.get_CellsSRC(7, 0, 0);BeginXCell.GlueTo(EndXCell);BeginXCell = connector.get_CellsU("EndX");EndXCell = EndShape.get_CellsSRC(7, 0, 0);BeginXCell.GlueTo(EndXCell);}/// <summary>/// 点P到直线AB的距离,P为线外一点,AB为线段两个端点/// </summary>/// <param name="pointA"></param>/// <param name="pointB"></param>/// <param name="P"></param>/// <returns></returns>private double GetPoint2Line(TxtPoint pointA,TxtPoint pointB, TxtPoint pointP){//P为线外一点,AB为线段两个端点//求直线方程double A = 0, B = 0, C = 0;A = pointA.Longtitude/3600000.0 - pointB.Longtitude/3600000.0;B = pointB.Latitude/3600000 - pointA.Latitude/3600000;C = pointA.Latitude/3600000 * pointB.Longtitude/3600000 - pointA.Longtitude/3600000 * pointB.Latitude/3600000;//代入点到直线距离公式double distance = 0;distance = (Math.Abs(A * pointP.Latitude/3600000 + B * pointP.Longtitude/3600000 + C)) / (Math.Sqrt(A * A + B * B));return distance;}private double GetPoint2Line(InfoEdits.Point pointA, InfoEdits.Point pointB, InfoEdits.Point pointP){//P为线外一点,AB为线段两个端点//求直线方程double A = 0, B = 0, C = 0;A = pointA.Lon - pointB.Lon;B = pointB.Lat - pointA.Lat;C = pointA.Lat * pointB.Lon - pointA.Lon * pointB.Lat;//代入点到直线距离公式double distance = 0;distance = (Math.Abs(A * pointP.Lat + B * pointP.Lon + C)) / (Math.Sqrt(A * A + B * B));if (!double.IsNaN(distance)){return distance;}else{return 0;}}private int ReturnTrackId(TxtPoint switchPoint,Dictionary<int,TxtPoint[]> dic){int trackid = 0;Dictionary<int,double> distance = new Dictionary<int, double>();foreach(KeyValuePair<int,TxtPoint[]> pair in dic){int key = pair.Key;distance.Add(key,(GetPoint2Line(dic[key][0], dic[key][1], switchPoint)));}var mindis = distance.Values.Min();trackid = distance.First(a => a.Value == mindis).Key;return trackid;}/// <summary>/// 通过比较直线外点和直线的距离判断属于哪个轨道/// </summary>/// <param name="pointP"></param>/// <param name="dic">int 轨道编号,Point[] 轨道的两个端点</param>/// <returns></returns>private int ReturnTrackId(InfoEdits.Point pointP, Dictionary<int, InfoEdits.Point[]> dic){int trackid = 0;Dictionary<int, double> distance = new Dictionary<int, double>();foreach (KeyValuePair<int, InfoEdits.Point[]> pair in dic){int key = pair.Key;distance.Add(key, (GetPoint2Line(dic[key][0], dic[key][1], pointP)));}var mindis = distance.Values.Min();trackid = distance.First(a => a.Value == mindis).Key;return trackid;}/***** 点到直线的距离:P到AB的距离*****///P为线外一点,AB为线段两个端点float getDist_P2L(Point pointP, Point pointA, Point pointB){//求直线方程int A = 0, B = 0, C = 0;A = pointA.Y - pointB.Y;B = pointB.X - pointA.X;C = pointA.X * pointB.Y - pointA.Y * pointB.X;//代入点到直线距离公式float distance = 0;distance = ((float)Math.Abs(A * pointP.X + B * pointP.Y + C)) / ((float)Math.Sqrt(A * A + B * B));return distance;}#endregion
