// 2018.12.12 public void getPaths1() { for (int i = 0; i < m_leaves.Count; i++) { Rays rays = new Rays(); Vector3 s = new Vector3(ref m_source.m_position); int nodeIndex = m_leaves[i]; // 收集多边形 int order = 0; // 只有靠近发射源的面 nodeIndex == 0 List <Vector3> pts = new List <Vector3>(); while (nodeIndex != 0) // m_polygonCache 中,第一个面是靠近目标的面,最后一个面是靠近发射源的面 { m_polygonCache[order++] = new Polygon(ref m_solutionNodes[nodeIndex].m_polygon); // 得到 poly 的中心 Polygon poly = m_solutionNodes[nodeIndex].m_clipedPolygon; float cx = 0, cy = 0, cz = 0; int n = poly.m_points.Count; for (int k = 0; k < n; k++) { cx += poly.m_points[k].x; cy += poly.m_points[k].y; cz += poly.m_points[k].z; } Vector3 pt = new Vector3(cx / n, cy / n, cz / n); pts.Add(pt); nodeIndex = m_solutionNodes[nodeIndex].m_parent; } bool ok = true; Vector3 t; int prePolyId = -1; for (int j = order - 1; j >= 0; j--) // 从靠近源的面开始 { Polygon poly = m_polygonCache[j]; t = pts[j]; Ray ray = new Ray(ref s, ref t); if (m_room.getKD().rayCastAny(ref ray, poly.m_id, prePolyId)) // 非法路径 { ok = false; break; } s = t; prePolyId = poly.m_id; NodeInfo rayInfo; if (j == order - 1) { rayInfo = Ray.createRay(ref ray); } else { Vector4 pleq = poly.getPleq(); rayInfo = Ray.createRay(ref ray, ref pleq); } rayInfo.buildingID = poly.m_buildingID; rays.m_rays.Add(rayInfo); } if (ok) // 整个路径段合法 { double rayAzimuth = 0; double rayIncination = 0; LTE.Geometric.Point startp = new Geometric.Point(rays.m_rays[0].PointOfIncidence.m_position.x, rays.m_rays[0].PointOfIncidence.m_position.y, rays.m_rays[0].PointOfIncidence.m_position.z); LTE.Geometric.Point endp = new Geometric.Point(rays.m_rays[0].CrossPoint.m_position.x, rays.m_rays[0].CrossPoint.m_position.y, rays.m_rays[0].CrossPoint.m_position.z); LTE.Geometric.GeometricUtilities.getAzimuth_Inclination(startp, endp, out rayAzimuth, out rayIncination); double[] ret = this.calcStrength.calcRayStrengthBeam(rayAzimuth, rayIncination, ref rays.m_rays); rays.emitPwrDbm = this.calcStrength.convertw2dbm(ret[2]); rays.recvPwrDbm = this.calcStrength.convertw2dbm(ret[0]); m_rays.Add(rays); } } }
// failPlane 也是输出结果 public void validatePath(ref Vector3 source, ref Vector3 target, int nodeIndex, ref Vector4 failPlane) { // 收集多边形 int order = 0; // 只有靠近发射源的面 nodeIndex == 0 while (nodeIndex != 0) // m_polygonCache 中,第一个面是靠近目标的面,最后一个面是靠近发射源的面 { m_polygonCache[order++] = m_solutionNodes[nodeIndex].m_polygon; nodeIndex = m_solutionNodes[nodeIndex].m_parent; } // 重建虚拟源 Vector3 imgSource = source; for (int i = order - 1; i >= 0; i--) // 从发射源开始重建虚拟源 { imgSource = Vector4.mirror(ref imgSource, m_polygonCache[i].getPleq()); } // 失败面测试 Vector3 s = imgSource; Vector3 t = target; bool missed = false; int missOrder = -1; Polygon missPoly = null; Ray missRay = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0)); bool missSide = false; for (int i = 0; i < order; i++) // 从靠近目标的面开始 { Polygon poly = m_polygonCache[i]; Vector4 pleq = poly.getPleq(); Ray ray = new Ray(ref s, ref t); // 射线完全位于障碍物的一边,不可能发射反射 if (Vector4.dot(ref s, ref pleq) * Vector4.dot(ref t, ref pleq) > 0) { missed = true; missSide = true; missOrder = i; missPoly = poly; missRay = ray; break; } // 射线没有与障碍物产生交点,不可能发生反射 if (!ray.intersectExt(ref poly)) { missed = true; missSide = false; missOrder = i; missPoly = poly; missRay = ray; break; } // 射线与障碍物的交点 2018.12.04 Vector3 isect = new Vector3(); NodeInfo rayInfo = Ray.intersect(ref ray, ref pleq, out isect); rayInfo.buildingID = poly.m_buildingID; m_raysCache[i] = rayInfo; s = Vector4.mirror(ref s, ref pleq); // 新的虚拟源 t = isect; m_validateCache[i * 2] = isect; m_validateCache[i * 2 + 1] = s; } // 传播失败面 if (missed) { Vector4 missPlane = new Vector4(0, 0, 0, 0); if (missSide) { // 根据面方程重建 missPlane = missPoly.getPleq(); if (Vector4.dot(ref missRay.m_a, ref missPlane) > 0) { missPlane.opNegative(); } } else { // 根据失败的 beam 边重建 Beam beam = new Beam(ref missRay.m_a, ref missPoly); missPlane = beam.getPleq(1); for (int i = 2; i < beam.numPleqs(); i++) { if (Vector4.dot(ref missRay.m_b, beam.getPleq(i)) < Vector4.dot(ref missRay.m_b, ref missPlane)) { missPlane = beam.getPleq(i); } } } // 传播失败面 for (int i = missOrder - 1; i >= 0; i--) // 从当前面到接近目标的面 { missPlane = Vector3.mirror(ref missPlane, m_polygonCache[i].getPleq()); } // 由于浮点精度,可能出错,重新计算 if (Vector4.dot(ref target, ref missPlane) > 0) { // 从失败面重建 beam Beam beam = new Beam(); imgSource = source; for (int i = order - 1; i >= 0; i--) { Polygon poly = m_polygonCache[i]; poly.clip(ref beam); imgSource = Vector4.mirror(ref imgSource, poly.getPleq()); beam = new Beam(ref imgSource, ref poly); } // 更新失败面 missPlane = getFailPlane(ref beam, ref target); } // 归一化 missPlane.normalize(); failPlane = missPlane; return; } // 检测路径是否合法 t = target; for (int i = 0; i < order; i++) // 从接收点开始检测 { Vector3 isect = m_validateCache[i * 2]; Ray ray = new Ray(ref isect, ref t); if (m_room.getKD().rayCastAny(ref ray)) { return; } t = isect; } Ray ray1 = new Ray(ref source, ref t); if (m_room.getKD().rayCastAny(ref ray1)) // 检测到发射源的路径是否合法 { return; } // 将合法路径加入结果 Path path = new Path(); path.m_order = order; path.m_points = new List <Vector3>(new Vector3[order + 2]); //path.m_polygons = new List<Polygon>(new Polygon[order]); // 2018.12.04 Rays rays = new Rays(order); if (order > 0) { m_raysCache[order - 1].PointOfIncidence = new Point(source.x, source.y, source.z); } t = target; for (int i = 0; i < order; i++) { path.m_points[order - i + 1] = t; // path.m_polygons[order - i - 1] = m_polygonCache[i]; t = m_validateCache[i * 2]; rays.m_rays[order - i - 1] = m_raysCache[i]; // 2018.12.04 } path.m_points[0] = source; path.m_points[1] = t; #region 将相似的路径移除---效果不明显 //float fval = Vector3.dot(path.m_points[1], new Vector3(1, 1, 1)); // //float fmin = fval - 2 * EPS_SIMILAR_PATHS; //float fmax = fval + 2 * EPS_SIMILAR_PATHS; //foreach (List<int> paths in m_pathFirstSet.Values) //{ // for (int i = 0; i < paths.Count; i++) // { // Path p = m_paths[paths[i]]; // if (p.m_order != order) // continue; // bool safe = false; // for (int k = 1; k < (int)p.m_points.Count - 1; k++) // { // if ((p.m_points[k] - path.m_points[k]).lengthSqr() > EPS_SIMILAR_PATHS * EPS_SIMILAR_PATHS) // { // safe = true; // break; // } // } // if (!safe) // return; // } //} //if (m_pathFirstSet.Keys.Contains(fval)) //{ // m_pathFirstSet[fval].Add(m_paths.Count); //} //else //{ // m_pathFirstSet[fval] = new List<int>(); // m_pathFirstSet[fval].Add(m_paths.Count); //} #endregion m_paths.Add(path); // 2018.12.04 最后一段射线 Vector3 pt0 = path.m_points[path.m_points.Count - 2]; Vector3 pt1 = path.m_points[path.m_points.Count - 1]; NodeInfo ray2; if (rays.m_rays.Count > 0) { ray2 = Ray.oneRay(pt0, pt1, RayType.VReflection); } else { ray2 = Ray.oneRay(pt0, pt1, RayType.Direction); } rays.m_rays.Add(ray2); m_rays.Add(rays); }
// 2018.12.13 public void getPaths() { for (int i = 0; i < m_leaves.Count; i++) { int nodeIndex = m_leaves[i]; // 收集 beam 多边形 int order = 0; List <List <Vector3> > pts = new List <List <Vector3> >(); // 每个多边形内的点 int maxCnt = 0, minCnt = 1000000; // 只有靠近发射源的面 nodeIndex == 0 while (nodeIndex != 0) // m_polygonCache 中,第一个面是靠近目标的面,最后一个面是靠近发射源的面 { m_polygonCache[order++] = new Polygon(ref m_solutionNodes[nodeIndex].m_polygon); List <Vector3> pt = m_solutionNodes[nodeIndex].m_polygon.getInerPoints(10, ref m_solutionNodes[nodeIndex].m_clipedPolygon.m_points); if (pt.Count == 0) { // 得到 poly 的中心 Polygon poly = m_solutionNodes[nodeIndex].m_clipedPolygon; float cx = 0, cy = 0, cz = 0; int n = poly.m_points.Count; for (int k = 0; k < n; k++) { cx += poly.m_points[k].x; cy += poly.m_points[k].y; cz += poly.m_points[k].z; } Vector3 tmp = new Vector3(cx / n, cy / n, cz / n); pt.Add(tmp); } pts.Add(pt); maxCnt = Math.Max(maxCnt, pt.Count); minCnt = Math.Min(minCnt, pt.Count); nodeIndex = m_solutionNodes[nodeIndex].m_parent; } int times = (maxCnt + minCnt) / 2; if (times == 0) { times = 1; } int pre = m_rays.Count; HashSet <String> pathExist = new HashSet <string>(); #region 随机组合 times 条主路径 for (int k = 0; k < times; k++) { string route = ""; bool ok = true; Vector3 t; int prePolyId = -1; Rays rays = new Rays(); Vector3 s = new Vector3(ref m_source.m_position); for (int j = order - 1; j >= 0; j--) // 从靠近源的面开始 { Polygon poly = m_polygonCache[j]; int id = rand.Next(0, pts[j].Count); t = pts[j][id]; route += string.Format("{0}", id) + ","; Ray ray = new Ray(ref s, ref t); if (m_room.getKD().rayCastAny(ref ray, poly.m_id, prePolyId)) // 非法路径 { ok = false; break; } s = t; prePolyId = poly.m_id; NodeInfo rayInfo; if (j == order - 1) { rayInfo = Ray.createRay(ref ray); } else { Vector4 pleq = poly.getPleq(); rayInfo = Ray.createRay(ref ray, ref pleq); } rayInfo.buildingID = poly.m_buildingID; if (double.IsNaN(rayInfo.Angle) || double.IsInfinity(rayInfo.Angle)) { ok = false; break; } if (pathExist.Contains(route)) // 该路径已经存在过了 { ok = false; } else { rays.m_rays.Add(rayInfo); } } if (ok) // 整个路径段合法 { pathExist.Add(route); double rayAzimuth = 0; double rayIncination = 0; LTE.Geometric.Point startp = new Geometric.Point(rays.m_rays[0].PointOfIncidence.m_position.x, rays.m_rays[0].PointOfIncidence.m_position.y, rays.m_rays[0].PointOfIncidence.m_position.z); LTE.Geometric.Point endp = new Geometric.Point(rays.m_rays[0].CrossPoint.m_position.x, rays.m_rays[0].CrossPoint.m_position.y, rays.m_rays[0].CrossPoint.m_position.z); LTE.Geometric.GeometricUtilities.getAzimuth_Inclination(startp, endp, out rayAzimuth, out rayIncination); double[] ret = this.calcStrength.calcRayStrengthBeam(rayAzimuth, rayIncination, ref rays.m_rays); rays.emitPwrDbm = this.calcStrength.convertw2dbm(ret[2]); rays.recvPwrDbm = this.calcStrength.convertw2dbm(ret[0]); m_rays.Add(rays); rayCount += rays.m_rays.Count; } } #endregion #region 加入最短主路径 2018.12.20 //if (m_rays.Count - pre > 0 && times > 1) //{ // List<Vector3> ss = new List<Vector3>(); // ss.Add(new Vector3(ref m_source.m_position)); // pts.Add(ss); // string route = ""; // Vector3[] path = plane(ref pts, maxCnt, ref route); // 多阶段图最短路径 // if (!pathExist.Contains(route)) // 该路径未被加入 // { // bool ok = true; // Vector3 t; // int prePolyId = -1; // Rays rays = new Rays(); // Vector3 s = path[order]; // for (int j = order - 1; j >= 0; j--) // 从靠近源的面开始 // { // Polygon poly = m_polygonCache[j]; // t = path[j]; // Ray ray = new Ray(ref s, ref t); // if (m_room.getKD().rayCastAny(ref ray, poly.m_id, prePolyId)) // 非法路径 // { // ok = false; // break; // } // s = t; // prePolyId = poly.m_id; // NodeInfo rayInfo; // if (j == order - 1) // { // rayInfo = Ray.createRay(ref ray); // } // else // { // Vector4 pleq = poly.getPleq(); // rayInfo = Ray.createRay(ref ray, ref pleq); // } // rayInfo.buildingID = poly.m_buildingID; // if (double.IsNaN(rayInfo.Angle) || double.IsInfinity(rayInfo.Angle)) // { // ok = false; // break; // } // rays.m_rays.Add(rayInfo); // } // if (ok) // 整个路径段合法 // { // double rayAzimuth = 0; // double rayIncination = 0; // LTE.Geometric.Point startp = new Geometric.Point(rays.m_rays[0].PointOfIncidence.m_position.x, rays.m_rays[0].PointOfIncidence.m_position.y, rays.m_rays[0].PointOfIncidence.m_position.z); // LTE.Geometric.Point endp = new Geometric.Point(rays.m_rays[0].CrossPoint.m_position.x, rays.m_rays[0].CrossPoint.m_position.y, rays.m_rays[0].CrossPoint.m_position.z); // LTE.Geometric.GeometricUtilities.getAzimuth_Inclination(startp, endp, out rayAzimuth, out rayIncination); // double[] ret = this.calcStrength.calcRayStrengthBeam(rayAzimuth, rayIncination, ref rays.m_rays); // rays.emitPwrDbm = this.calcStrength.convertw2dbm(ret[2]); // rays.recvPwrDbm = this.calcStrength.convertw2dbm(ret[0]); // m_rays.Add(rays); // } // } //} #endregion } }