/// <summary>
        /// 计算点连接圆的两条切线(用来处理起点和终点)
        /// </summary>
        private static void HandlePointCircleEdges(CircleGraphNode p, Circle c, List <Circle> circles, List <CircleGraphNode> nodes)
        {
            float   d     = Vector2.Distance(c.center, p.Center);
            float   theta = Mathf.Acos(c.radius / d);
            Vector2 toP   = p.Center - c.center;
            float   alpha = Mathf.Atan2(toP.y, toP.x);

            var c1 = c.center + new Vector2(Mathf.Cos(alpha + theta), Mathf.Sin(alpha + theta)) * c.radius;
            var e1 = new Edge(p.Center, c1);
            var c2 = c.center + new Vector2(Mathf.Cos(alpha - theta), Mathf.Sin(alpha - theta)) * c.radius;
            var e2 = new Edge(p.Center, c2);

            bool isValid1 = true, isValid2 = true;

            for (int i = 0; i < circles.Count; i++)
            {
                if (ReferenceEquals(circles[i], c))
                {
                    continue;
                }

                if (isValid1 && !circles[i].CheckLineOfSignt(e1))
                {
                    isValid1 = false;
                }
                if (isValid2 && !circles[i].CheckLineOfSignt(e2))
                {
                    isValid2 = false;
                }
                if (!isValid1 && !isValid2)
                {
                    break;
                }
            }

            if (isValid1)
            {
                CircleGraphNode gb = new CircleGraphNode(e1.b, c);
                p.AddNeighbor(gb);
                gb.AddNeighbor(p);
                nodes.Add(gb);
                c.surfingPoints.Add(gb);
            }

            if (isValid2)
            {
                CircleGraphNode gb = new CircleGraphNode(e2.b, c);
                p.AddNeighbor(gb);
                gb.AddNeighbor(p);
                nodes.Add(gb);
                c.surfingPoints.Add(gb);
            }
        }
        private static List <CircleGraphNode> BruteForce(Vector2 start, Vector2 end, List <Circle> obstacles)
        {
            List <CircleGraphNode> result = new List <CircleGraphNode>();

            for (int i = 0; i < obstacles.Count; i++)
            {
                obstacles[i].surfingPoints.Clear();
            }

            CircleGraphNode startNode = new CircleGraphNode(start, null);
            CircleGraphNode endNode   = new CircleGraphNode(end, null);

            result.Add(startNode);
            result.Add(endNode);

            for (int i = 0; i < obstacles.Count; i++)
            {
                var a = obstacles[i];

                //连接起点和终点
                HandlePointCircleEdges(startNode, a, obstacles, result);
                HandlePointCircleEdges(endNode, a, obstacles, result);

                //到别的圆的链接
                for (int j = i + 1; j < obstacles.Count; j++)
                {
                    var b = obstacles[j];

                    var internalBitangents = InternalBitangents(a, b);
                    HandleEdges(a, b, obstacles, internalBitangents, result);

                    var externalBitangents = ExternalBitangents(a, b);
                    HandleEdges(a, b, obstacles, externalBitangents, result);
                }

                //本圆的链接
                for (int j = 0; j < a.surfingPoints.Count - 1; j++)
                {
                    for (int k = j + 1; k < a.surfingPoints.Count; k++)
                    {
                        var ga = a.surfingPoints[j];
                        var gb = a.surfingPoints[k];
                        ga.AddNeighbor(gb);
                        gb.AddNeighbor(ga);
                    }
                }
            }

            return(result);
        }
        private static void HandleEdges(Circle a, Circle b, List <Circle> circles, List <Edge> edges, List <CircleGraphNode> nodes)
        {
            if (edges == null)
            {
                return;
            }

            for (int index = 0; index < circles.Count; index++)
            {
                var c = circles[index];
                if (ReferenceEquals(a, c) || ReferenceEquals(b, c))
                {
                    continue;
                }

                for (int i = edges.Count - 1; i >= 0; i--)
                {
                    var e = edges[i];
                    if (!c.CheckLineOfSignt(e))
                    {
                        edges.RemoveAt(i);
                    }
                }

                if (edges.Count <= 0)
                {
                    break;
                }
            }

            for (int i = 0; i < edges.Count; i++)
            {
                var ga = new CircleGraphNode(edges[i].a, a);
                a.surfingPoints.Add(ga);
                nodes.Add(ga);

                var gb = new CircleGraphNode(edges[i].b, b);
                b.surfingPoints.Add(gb);
                nodes.Add(gb);

                ga.AddNeighbor(gb);
                gb.AddNeighbor(ga);
            }
        }
예제 #4
0
 public CircleGraphAStar(CircleGraphNode startNode, CircleGraphNode endNode) : base(startNode, endNode)
 {
 }