/// <summary> /// 相对原点的多边形边界 /// </summary> /// <param name="source"></param> /// <param name="vertex"></param> /// <param name="mintheta"></param> /// <param name="maxtheta"></param> /// <param name="distance"></param> /// <returns></returns> public static bool getBoundPointIndex(Point source, List <Point> vertex, ref TriangleBound tb) { bool isEdge; int startIndex = 0; //原点是否在多边形内部 if (GeometricUtilities.PointInPolygon(vertex.ToArray(), source, out isEdge, ref startIndex)) { return(false); } tb.maxIndex = -1; tb.maxTheta = -1; tb.minIndex = int.MaxValue - 500; tb.minTheta = 1000; tb.totalVertex = vertex.Count; double theta; Dictionary <int, Polar> tmp = new Dictionary <int, Polar>(); int cnt = vertex.Count; Polar p; //求相对原点的极坐标,根据theta角判断边界 for (int i = 0; i < cnt; i++) { p = GeometricUtilities.getPolarCoord(source, vertex[i]); theta = p.theta; tmp.Add(i, p); if (theta < tb.minTheta) { tb.minIndex = i; tb.minTheta = theta; } if (theta > tb.maxTheta) { tb.maxIndex = i; tb.maxTheta = theta; } } //说明多边形与x轴相交 if (tb.maxTheta - tb.minTheta > Math.PI) { double th; tb.maxIndex = -1; tb.maxTheta = -1; tb.minIndex = int.MaxValue - 500; tb.minTheta = 1000; foreach (var kv in tmp) { th = kv.Value.theta; if (th < Math.PI) { if (th > tb.maxTheta) { tb.maxIndex = kv.Key; tb.maxTheta = th; } } else if (th < tb.minTheta) { tb.minIndex = kv.Key; tb.minTheta = th; } } } tb.stob = tmp[tb.minIndex].r > tmp[(tb.minIndex + 1) % cnt].r; return(true); }
/// <summary> /// 获取一个建筑物棱边绕射点 /// </summary> /// <param name="baseHeight"></param> /// <param name="tb"></param> /// <param name="gridLength"></param> /// <returns></returns> private static List <Point> getOneBuildingEdgePointsByShelter(double baseHeight, TriangleBound tb, double gridLength) { List <Point> ret = new List <Point>(); Point t; List <Point> v = buildingVertex[tb.buildingid]; //获取垂直棱边 for (int i = tb.minIndex, e = (tb.maxIndex + 1) % tb.totalVertex; i != e; i = (i + 1) % tb.totalVertex) { double d = gridLength / 2; for (double j = tb.baseHeight + d; j < tb.height - d; j += gridLength) { t = new Point(v[i]); t.Z = j; ret.Add(t); } } //获取水平棱边 //for (int i = tb.minIndex, e = (tb.maxIndex + 1) % tb.totalVertex; i != e; i = (i + 1) % tb.totalVertex) //{ // List<Point> tmp = VerticalPlaneGrid.GetHEdgePoints(v[i], v[(i + 1) % tb.totalVertex], gridLength, tb.height); // ret.AddRange(tmp); //} if (baseHeight > tb.height) { for (int i = 0; i < tb.totalVertex - 1; i++) { List <Point> tmp = VerticalPlaneGrid.GetHEdgePoints(v[i], v[(i + 1) % tb.totalVertex], gridLength, tb.height); ret.AddRange(tmp); } } else { int i = tb.minIndex, end = (tb.maxIndex + 1) % tb.totalVertex; int j = (i - 1 + tb.totalVertex) % tb.totalVertex; for (; i != end; j = i, i = (i + 1) % tb.totalVertex) { List <Point> tmp = VerticalPlaneGrid.GetHEdgePoints(v[i], v[j], gridLength, tb.height); ret.AddRange(tmp); } } return(ret); }
/// <summary> /// 求比基准高度高的建筑物遮挡距离和角度范围 /// </summary> /// <param name="source"></param> /// <param name="buildingids"></param> /// <param name="baseHeight"></param> /// <returns></returns> /// /// <summary> /// 建筑物遮挡关系(极坐标系) /// </summary> /* * public struct TriangleBound * { * //建筑物id * public int buildingid; * public int totalVertex; * //角度最小的边界点的索引 * public int minIndex; * public double minTheta; * //角度最大的边界点的索引 * public int maxIndex; * public double maxTheta; * //离原点较近的边是否是从minIndex到maxIndex * public bool stob; * //原点与建筑物的距离(近似值) * public double distance; * //违背遮挡高度 * public double baseHeight; * //建筑物高度 * public double height; * } */ public static List <TriangleBound> getShelterDisAndAngle(Point source, List <int> buildingids, double baseHeight) { Dictionary <int, TriangleBound> bdis = new Dictionary <int, TriangleBound>(); TriangleBound tb = new TriangleBound(); double height, sz = baseHeight, altitude; int bid; for (int i = 0, cnt = buildingids.Count; i < cnt; i++) { bid = buildingids[i]; height = buildingHeight[bid]; altitude = buildingAltitude[bid]; // 地形 if (height > sz) { tb = new TriangleBound(); tb.height = height; tb.baseHeight = altitude; // 地形 tb.distance = GeometricUtilities.GetDistanceOf2DPoints(source, buildingCenter[bid]); bdis[bid] = tb; } } List <KeyValuePair <int, TriangleBound> > bdisOrder = bdis.OrderBy(c => c.Value.distance).ToList(); List <TriangleBound> ret = new List <TriangleBound>(); foreach (var kv in bdisOrder) { bid = kv.Key; tb = bdis[bid]; // 得到每个建筑物相对于原点的最小、最大角度 if (getBoundPointIndex(source, buildingVertex[bid], ref tb)) { tb.buildingid = bid; ret.Add(tb); } } //去掉一些遮挡的 double min1, max1, min2, max2; for (int i = ret.Count - 1; i > 0; i--) { for (int j = i - 1; j >= 0; j--) { min1 = ret[j].minTheta; max1 = ret[j].maxTheta; min2 = ret[i].minTheta; max2 = ret[i].maxTheta; // j比i范围广,且在i前面 if (max2 < max1 && min2 > min1) { if (ret[j].height >= ret[i].height) // j完全挡住了i { ret.RemoveAt(i); break; } else if (ret[j].height > ret[i].baseHeight) // j部分遮住了i { TriangleBound tt = ret[i]; // 更新i的可见度 tt.baseHeight = Math.Max(ret[j].height, tt.baseHeight); // 地形 ret[i] = tt; } } } } return(ret); }