public Scatter(LineSegment[] segs, SCATTER_SEG_DIRECTION direction=SCATTER_SEG_DIRECTION.CLOCKWISE, double dc=2, string name="") { if (!IsSegmentsLegal(segs)) throw new Exception("线段集合不符合要求,请保证:\n" + "1. 至少有3条线段\n" + "2. 集合内的线段按序首尾相连\n" + "3. 每条线段都不与除相临线段外的任何线段相交\n"); this.border_segments = segs; this.seg_direction = direction; this.dielectric_constant = dc; int top = int.MaxValue, bottom = int.MinValue, left = int.MaxValue, right = int.MinValue; foreach(LineSegment seg in segs) { if (seg.Top < top) top = seg.Top; if (seg.Bottom > bottom) bottom = seg.Bottom; if (seg.Left < left) left = seg.Left; if (seg.Right > right) right = seg.Right; } this.border_rect.X = left; this.border_rect.Y = top; this.border_rect.Width = right - left; this.border_rect.Height = bottom - top; this.name = name == "" ? "Scatter" + id.ToString() : name; id++; }
///// <summary> ///// 自由空间路径损耗 ///// </summary> ///// <param name="Pi"></param> ///// <param name="d"></param> ///// <param name="freq"></param> ///// <returns></returns> //public static double FreeSpacePathLoss(double Pi, double d, double freq) //{ // double dbi = 20 * Math.Log10(freq / 1e6) + 20 * Math.Log10(d / 1e3); // double ratio = Math.Pow(10, (dbi / 10)); // return Pi / ratio; //} /// <summary> /// 计算镜面反射角 /// </summary> /// <param name="ray">入射波束线段</param> /// <param name="barrier">产生碰撞的散射体线段</param> /// <param name="dir">散射体的向量旋转方向</param> /// /// <returns>出射角</returns> public static double SpecularReflection(LineSegment ray, LineSegment barrier, SCATTER_SEG_DIRECTION dir) { double result; double angle = ray.Angle(barrier); if(dir == SCATTER_SEG_DIRECTION.CLOCKWISE) { result = barrier.DirectionRadian + angle; result = result > Math.PI * 2 ? result - Math.PI * 2 : result; } else { result = barrier.DirectionRadian - angle; result = result < 0 ? result + Math.PI * 2 : result; } return result; }
public Scatter(Point[] vertices, SCATTER_SEG_DIRECTION direction=SCATTER_SEG_DIRECTION.CLOCKWISE, double dc=2, string name="") { Exception ex = new Exception("顶点集合不符合要求,请保证:\n" + "1. 至少有3个顶点\n" + "2. 顶点按序连成的每条线段都不与除相临线段外的任何线段相交\n"); if (vertices.Length < 3) throw ex; List<LineSegment> segs = new List<LineSegment>(); for(int i = 1; i < vertices.Length; i++) { segs.Add(new LineSegment(vertices[i - 1], vertices[i])); } segs.Add(new LineSegment(vertices[vertices.Length - 1], vertices[0])); LineSegment[] sgs = segs.ToArray(); if (!IsSegmentsLegal(sgs)) throw ex; this.border_segments = sgs; this.seg_direction = direction; this.dielectric_constant = dc; int top = int.MaxValue, bottom = int.MinValue, left = int.MaxValue, right = int.MinValue; foreach (LineSegment seg in segs) { if (seg.Top < top) top = seg.Top; if (seg.Bottom > bottom) bottom = seg.Bottom; if (seg.Left < left) left = seg.Left; if (seg.Right > right) right = seg.Right; } this.border_rect.X = left; this.border_rect.Y = top; this.border_rect.Width = right - left; this.border_rect.Height = bottom - top; this.name = name == "" ? "Scatter" + id.ToString() : name; id++; }
/// <summary> /// 获取反射点坐标及碰撞线段和碰撞散射体的旋转方向 /// </summary> /// <param name="seg"></param> /// <param name="collision_seg"></param> /// <param name="dir"></param> /// <returns></returns> public Point? GetClosestReflectionPoint(LineSegment seg, out LineSegment collision_seg, out SCATTER_SEG_DIRECTION dir, out double dc) { Dictionary<Point?, object[]> pt_seg_dir_dict = new Dictionary<Point?, object[]>(); foreach (Scatter scatter in this.Scatters) { Point? tmp_pt = null; LineSegment tmp_seg = null; SCATTER_SEG_DIRECTION tmp_dir = scatter.SegDirection; double tmp_dc = scatter.DielectricConstant; tmp_pt = scatter.GetClosestReflectionPoint(seg, out tmp_seg); if (tmp_pt != null) pt_seg_dir_dict.Add(tmp_pt, new object[] { tmp_seg, tmp_dir, tmp_dc }); } if(pt_seg_dir_dict.Count == 0) //没有交点 { collision_seg = null; dir = SCATTER_SEG_DIRECTION.CLOCKWISE; dc = 0; return null; } KeyValuePair<Point?, object[]> tmp_kvp = pt_seg_dir_dict.First(); double min_d2 = double.PositiveInfinity; foreach (KeyValuePair<Point?, object[]> kvp in pt_seg_dir_dict) { double dist2 = Math.Pow(kvp.Key.Value.X - seg.TailPosition.X, 2) + Math.Pow(kvp.Key.Value.Y - seg.TailPosition.Y, 2); if (dist2 > 0 && dist2 < min_d2) { min_d2 = dist2; tmp_kvp = kvp; } } collision_seg = tmp_kvp.Value[0] as LineSegment; dir = (SCATTER_SEG_DIRECTION)tmp_kvp.Value[1]; dc = (double)tmp_kvp.Value[2]; return tmp_kvp.Key; }