Example #1
0
        //------------------------------------------------------------------------
        public void beamTracingPath()
        {
            Vector3 source = m_source.getPosition();
            Vector3 target = m_listener.getPosition();

            m_paths.Clear();

            if (m_solutionNodes.Count == 0 || m_cachedSource.x != source.x || m_cachedSource.y != source.y || m_cachedSource.z != source.z)  // target 改变后不影响
            {
                clearCache();

                SolutionNode root = new SolutionNode();  // beam 根节点
                root.m_polygon = null;
                root.m_parent  = -1;
                m_solutionNodes.Add(root);  // 记录障碍物面及父 beam id

                DateTime t0   = DateTime.Now;
                Beam     beam = new Beam();

                m_cachedSource.x = source.x;
                m_cachedSource.y = source.y;
                m_cachedSource.z = source.z;

                Path path = new Path();
                buildBeamTree(ref source, ref beam, 0, 0);

                DateTime t1 = DateTime.Now;
                Console.WriteLine("beam 树建立时间:{0} s", (t1 - t0).TotalMilliseconds / 1000);
                Console.WriteLine(string.Format("beam 树节点总数:{0}", m_solutionNodes.Count));
                Console.WriteLine(string.Format("beam 树叶节点总数:{0}", m_leaves.Count));

                getPaths();     // 获取多条主路径
                //getPaths1();  // 只获取一条主路径
            }
        }
Example #2
0
        // 2018.12.12
        // 建立 beam 树,得到 m_solutionNodes,去掉部分遮挡
        // 存储每个 beam 节点中离目标点最近的 beam 侧面
        public void buildBeamTree1(ref Vector3 source, ref Vector3 target, ref Beam beam, int order, int parentIndex)
        {
            m_failPlanes.Add(new Vector4(getFailPlane(ref beam, ref target)));  // 离目标点最近的面

            if (order >= m_maximumOrder)
            {
                m_leaves.Add(m_solutionNodes.Count - 1);
                return;
            }

            List <Polygon> polygons = new List <Polygon>();

            m_room.getKD().beamCast(ref beam, ref polygons);

            HashSet <int> pid = getPolygonsID(beam.getTop(), ref polygons); // 得到未被遮挡的建筑物面 2019.1.2

            for (int i = (int)polygons.Count - 1; i >= 0; i--)              // 当前 KD 节点中包含的所有多边形
            {
                Polygon orig      = polygons[i];
                Vector3 imgSource = Vector4.mirror(ref source, orig.getPleq());

                if (parentIndex > 0)  // 有父 beam,跳过一些特殊情况
                {
                    Polygon ppoly = m_solutionNodes[parentIndex].m_polygon;
                    if (orig.m_id == ppoly.m_id)  // 如果与上一个面是同一个面,跳过
                    {
                        continue;
                    }

                    Vector3 testSource = Vector4.mirror(ref imgSource, ppoly.getPleq());
                    if ((source - testSource).length() < EPS_SIMILAR_PATHS)  // 如果与上一个源相距太近
                    {
                        continue;
                    }
                }
                else  // 2018.12.11  被遮挡的面不构成第一级反射 beam
                {
                    if (!orig.m_first)
                    {
                        continue;
                    }
                }

                if (!pid.Contains(orig.m_buildingID))  // 完全被遮挡的建筑物面  2019.1.2
                {
                    continue;
                }

                Polygon poly = new Polygon(ref orig);
                if (poly.clip(ref beam) == Polygon.ClipResult.CLIP_VANISHED)
                {
                    continue;
                }

                if (poly.getArea() < EPS_DEGENERATE_POLYGON_AREA)
                {
                    continue;
                }

                Beam b = new Beam(ref imgSource, ref poly);

                SolutionNode node = new SolutionNode();
                node.m_polygon       = orig;
                node.m_clipedPolygon = poly;
                node.m_parent        = parentIndex;
                m_solutionNodes.Add(node);

                buildBeamTree1(ref imgSource, ref target, ref b, order + 1, m_solutionNodes.Count - 1);
            }
        }
Example #3
0
        // 建立 beam 树,得到 m_solutionNodes,不考虑遮挡
        // 存储每个 beam 节点中离目标点最近的 beam 侧面
        public void solveRecursive(ref Vector3 source, ref Vector3 target, ref Beam beam, int order, int parentIndex)
        {
            m_failPlanes.Add(new Vector4(getFailPlane(ref beam, ref target)));  // 离目标点最近的面

            if (order >= m_maximumOrder)
            {
                return;
            }

            List <Polygon> polygons = new List <Polygon>();

            m_room.getKD().beamCast(ref beam, ref polygons);
            for (int i = (int)polygons.Count - 1; i >= 0; i--)  // 当前 KD 节点中包含的所有多边形
            {
                Polygon orig      = polygons[i];
                Vector3 imgSource = Vector4.mirror(ref source, orig.getPleq());

                if (parentIndex > 0)  // 有父 beam,跳过一些特殊情况
                {
                    Polygon ppoly = m_solutionNodes[parentIndex].m_polygon;
                    if (orig.m_id == ppoly.m_id)  // 如果与上一个面是同一个面,跳过
                    {
                        continue;
                    }

                    Vector3 testSource = Vector4.mirror(ref imgSource, ppoly.getPleq());
                    if ((source - testSource).length() < EPS_SIMILAR_PATHS)  // 如果与上一个源相距太近
                    {
                        continue;
                    }
                }
                else  // 2018.12.11  被遮挡的面不构成初级 beam
                {
                    if (!orig.m_first)
                    {
                        continue;
                    }
                }

                Polygon poly = new Polygon(ref orig);
                if (poly.clip(ref beam) == Polygon.ClipResult.CLIP_VANISHED)
                {
                    continue;
                }

                if (poly.getArea() < EPS_DEGENERATE_POLYGON_AREA)
                {
                    continue;
                }

                Beam b = new Beam(ref imgSource, ref poly);

                SolutionNode node = new SolutionNode();
                node.m_polygon = orig;
                //node.m_clipedPolygon = poly;
                node.m_parent = parentIndex;
                m_solutionNodes.Add(node);

                solveRecursive(ref imgSource, ref target, ref b, order + 1, m_solutionNodes.Count - 1);

                //if (order == 0)
                //   Console.WriteLine("building beam tree.. {0}% ({1}) {2}\r", 100 - (float)i / (float)polygons.Count() * 100, m_solutionNodes.Count, m_node++);
            }

            //if (order == 0)
            //{
            //    Console.WriteLine("{0}", m_level++);
            //}
        }
Example #4
0
        public void beamTracing()
        {
            int numProc   = 0;
            int numTested = 0;

            Vector3 source = m_source.getPosition();
            Vector3 target = m_listener.getPosition();

            m_paths.Clear();

            // 只有当发射源改变了才会重新建立beam
            if (m_solutionNodes.Count == 0 || m_cachedSource.x != source.x || m_cachedSource.y != source.y || m_cachedSource.z != source.z)  // target 改变后不影响
            {
                clearCache();

                SolutionNode root = new SolutionNode();  // beam 根节点
                root.m_polygon = null;
                root.m_parent  = -1;
                m_solutionNodes.Add(root);  // 记录障碍物面及父 beam id

                DateTime t0   = DateTime.Now;
                Beam     beam = new Beam();
                buildBeamTree1(ref source, ref target, ref beam, 0, 0);  // 得到 m_solutionNodes,m_failPlanes
                //solveRecursive(ref source, ref target, ref beam, 0, 0);  // 得到 m_solutionNodes,m_failPlanes
                DateTime t1 = DateTime.Now;
                Console.WriteLine("束树建立时间:{0} s", (t1 - t0).TotalMilliseconds / 1000);
                Console.WriteLine(string.Format("束树节点总数:{0}", m_solutionNodes.Count));

                m_cachedSource.x = source.x;
                m_cachedSource.y = source.y;
                m_cachedSource.z = source.z;

                // 设置桶的数量
                // numBuckets <= m_s//olutionNodes.size()
                int numBuckets = (m_solutionNodes.Count + DISTANCE_SKIP_BUCKET_SIZE - 1) / DISTANCE_SKIP_BUCKET_SIZE;
                m_distanceSkipCache = new List <Vector4>();
                for (int i = 0; i < numBuckets; i++)
                {
                    m_distanceSkipCache.Add(new Vector4(0, 0, 0, 0));
                }
            }

            int            n          = m_solutionNodes.Count;
            int            nb         = (m_solutionNodes.Count + DISTANCE_SKIP_BUCKET_SIZE - 1) / DISTANCE_SKIP_BUCKET_SIZE; // numBuckets
            List <Vector4> skipSphere = m_distanceSkipCache;

            for (int b = 0; b < nb; b++)
            {
                Vector4 fc = skipSphere[b];
                Vector3 r  = target - new Vector3(fc.x, fc.y, fc.z); // 与障碍物的距离
                if (r.lengthSqr() < fc.w)                            // 接收点位于忽略球内,忽略所有路径测试。
                {
                    continue;
                }

                float maxdot = 0;
                numProc++;

                int imn = b * DISTANCE_SKIP_BUCKET_SIZE;   // 第 b 个桶
                int imx = imn + DISTANCE_SKIP_BUCKET_SIZE;
                if (imx > n)
                {
                    imx = n;
                }
                for (int i = imn; i < imx; i++)
                {
                    float d = Vector4.dot(ref target, m_failPlanes[i]);

                    if (d >= 0)  // 在失败面的前面,也就是在 beam 面的后面,可能有合法路径
                    {
                        Vector4 failPlane = m_failPlanes[i];
                        validatePath(ref source, ref target, i, ref failPlane);  // 验证路径,更新 m_failPlanes[i],m_path
                        m_failPlanes[i] = failPlane;
                        int cnt = m_paths.Count;
                        numTested++;
                    }
                    if (i == imn || d > maxdot)
                    {
                        maxdot = d;
                    }
                }

                if (maxdot < 0)   // 桶中的所有节点都失败了,便可计算失败面到接收点的最短距离,作为半径,而接收点为球心
                {
                    m_distanceSkipCache[b].set(target.x, target.y, target.z, maxdot * maxdot);
                }
            }

            m_pathFirstSet.Clear();
        }