Exemplo n.º 1
0
        //TODO: maybe need to generate a height map file as well just for this, because it takes a long time
        private void BuildGraph()
        {
            Logger.LogPathfinding(
                $"PathfinderData.BuildGraph()",
                LogLevel.DEBUG);
            // TODO: Add nodes for terrain features


            /*// Fill in any big open spaces with a sparse grid in case the above missed anything important
             * Vector3 newPos = new Vector3(0f, 0f, 0f);
             * for (float x = -size.x/2; x < size.x/2; x += SparseGridSpacing / 10) {
             *  for (float z = -size.z/2; z < size.z/2; z += SparseGridSpacing / 10) {
             *      newPos.Set(x, 0f, z);
             *
             *      float minDist = float.MaxValue;
             *      foreach (PathNode node in graph)
             *          minDist = Mathf.Min(minDist, Vector3.Distance(newPos, node.position));
             *
             *      if (minDist > SparseGridSpacing)
             *          graph.Add(new PathNode(newPos));
             *  }
             * }*/

            // Remove nodes that are right on top of each other
            for (int i = 0; i < _graphFastMove.Count; i++)
            {
                for (int j = i + 1; j < _graphFastMove.Count; j++)
                {
                    if ((Position(_graphFastMove[i]) - Position(_graphFastMove[j])).magnitude < NODE_PRUNE_DIST_THRESH)
                    {
                        _graphFastMove.RemoveAt(j);
                    }
                }
            }

            _openSet = new FastPriorityQueue <PathNode>(_graphFastMove.Count + 1);


            // find all nodes that are around bridges. This will help pathfinding
            // when not in fast move mode.
            foreach (PathNode pn in _graphFastMove)
            {
                foreach (Vector3 bridge in _map.Bridges())
                {
                    Vector3 pnPos = new Vector3(pn.x, pn.y, pn.z);
                    if (pn.IsRoad && (pnPos - bridge).magnitude < ARC_MAX_DIST / 2)
                    {
                        _graphRegularMove.Add(new PathNode(pnPos, true));
                    }
                }
            }

            for (int i = 0; i < _graphRegularMove.Count; i++)
            {
                for (int j = i + 1; j < _graphRegularMove.Count; j++)
                {
                    if ((Position(_graphRegularMove[i]) - Position(_graphRegularMove[j])).magnitude < ARC_MAX_DIST)
                    {
                        AddArc(_graphRegularMove[i], _graphRegularMove[j]);
                    }
                }
            }

            // Compute arcs for all pairs of nodes within cutoff distance
            // we are attempting to create a connected graph here with each edge
            // representing time/value for each mobility type at the node
            for (int i = 0; i < _graphFastMove.Count; i++)
            {
                for (int j = i + 1; j < _graphFastMove.Count; j++)
                {
                    if ((Position(_graphFastMove[i]) - Position(_graphFastMove[j])).magnitude < ARC_MAX_DIST)
                    {
                        AddArc(_graphFastMove[i], _graphFastMove[j]);
                    }
                }

                double percent = ((double)i / (double)_graphFastMove.Count) * 100.0;
                SetPercentComplete(percent);
            }



            // leave this for now in case things get a little crazy for path finding later

            // Remove unnecessary arcs.
            // An arc in necessary if for any MobilityType, the direct path
            // between the nodes is at least as good as the optimal global path.
            // This is a brute force approach and it might be too slow.
            //List<PathNode> path = new List<PathNode>();

            //for (int i = 0; i < _graph.Count; i++)
            //{
            //    for (int j = i + 1; j < _graph.Count; j++)
            //    {
            //        PathArc arc = GetArc(_graph[i], _graph[j]);
            //        if (arc.Equals(INVALID_ARC))
            //            continue;

            //        bool necessary = false;
            //        foreach (MobilityData mobility in _mobilityTypes)
            //        {
            //            if (arc.Time[mobility.Index] == Pathfinder.FOREVER)
            //                continue;

            //            float time = FindPath(path,
            //                    Position(_graph[i]), Position(_graph[j]),
            //                    mobility, 0f, MoveCommandType.FAST);



            //            if (arc.Time[mobility.Index] < 1.5 * time)
            //            {
            //                necessary = true;
            //                break;
            //            }

            //        }

            //        if (!necessary)
            //            RemoveArc(_graph[i], _graph[j]);
            //    }

            //    double percent = ((double)i / (double)_graph.Count) * 100.0;
            //    SetPercentComplete(percent);

            //if ((int)percent % 2 == 0)
            //{
            //    yield return null;
            //}

            //}
        }