123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- using Pathfinding.Util;
- using System.Collections.Generic;
- using UnityEngine;
- namespace Pathfinding {
-
-
-
-
-
-
-
- public static class PathUtilities {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static bool IsPathPossible (GraphNode node1, GraphNode node2) {
- return node1.Walkable && node2.Walkable && node1.Area == node2.Area;
- }
-
-
-
-
-
-
-
-
-
- public static bool IsPathPossible (List<GraphNode> nodes) {
- if (nodes.Count == 0) return true;
- uint area = nodes[0].Area;
- for (int i = 0; i < nodes.Count; i++) if (!nodes[i].Walkable || nodes[i].Area != area) return false;
- return true;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static bool IsPathPossible (List<GraphNode> nodes, int tagMask) {
- if (nodes.Count == 0) return true;
-
- if (((tagMask >> (int)nodes[0].Tag) & 1) == 0) return false;
-
- if (!IsPathPossible(nodes)) return false;
-
- var reachable = GetReachableNodes(nodes[0], tagMask);
- bool result = true;
-
- for (int i = 1; i < nodes.Count; i++) {
- if (!reachable.Contains(nodes[i])) {
- result = false;
- break;
- }
- }
-
- ListPool<GraphNode>.Release(ref reachable);
- return result;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static List<GraphNode> GetReachableNodes (GraphNode seed, int tagMask = -1, System.Func<GraphNode, bool> filter = null) {
- Stack<GraphNode> dfsStack = StackPool<GraphNode>.Claim();
- List<GraphNode> reachable = ListPool<GraphNode>.Claim();
-
- var map = new HashSet<GraphNode>();
- System.Action<GraphNode> callback;
-
- if (tagMask == -1 && filter == null) {
- callback = (GraphNode node) => {
- if (node.Walkable && map.Add(node)) {
- reachable.Add(node);
- dfsStack.Push(node);
- }
- };
- } else {
- callback = (GraphNode node) => {
- if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && map.Add(node)) {
- if (filter != null && !filter(node)) return;
- reachable.Add(node);
- dfsStack.Push(node);
- }
- };
- }
- callback(seed);
- while (dfsStack.Count > 0) {
- dfsStack.Pop().GetConnections(callback);
- }
- StackPool<GraphNode>.Release(dfsStack);
- return reachable;
- }
- static Queue<GraphNode> BFSQueue;
- static Dictionary<GraphNode, int> BFSMap;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static List<GraphNode> BFS (GraphNode seed, int depth, int tagMask = -1, System.Func<GraphNode, bool> filter = null) {
- #if ASTAR_PROFILE
- System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
- watch.Start();
- #endif
- BFSQueue = BFSQueue ?? new Queue<GraphNode>();
- var que = BFSQueue;
- BFSMap = BFSMap ?? new Dictionary<GraphNode, int>();
- var map = BFSMap;
-
-
-
-
- que.Clear();
- map.Clear();
- List<GraphNode> result = ListPool<GraphNode>.Claim();
- int currentDist = -1;
- System.Action<GraphNode> callback;
- if (tagMask == -1) {
- callback = node => {
- if (node.Walkable && !map.ContainsKey(node)) {
- if (filter != null && !filter(node)) return;
- map.Add(node, currentDist+1);
- result.Add(node);
- que.Enqueue(node);
- }
- };
- } else {
- callback = node => {
- if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && !map.ContainsKey(node)) {
- if (filter != null && !filter(node)) return;
- map.Add(node, currentDist+1);
- result.Add(node);
- que.Enqueue(node);
- }
- };
- }
- callback(seed);
- while (que.Count > 0) {
- GraphNode n = que.Dequeue();
- currentDist = map[n];
- if (currentDist >= depth) break;
- n.GetConnections(callback);
- }
- que.Clear();
- map.Clear();
- #if ASTAR_PROFILE
- watch.Stop();
- Debug.Log((1000*watch.Elapsed.TotalSeconds).ToString("0.0 ms"));
- #endif
- return result;
- }
-
-
-
-
-
-
-
-
-
-
-
-
- public static List<Vector3> GetSpiralPoints (int count, float clearance) {
- List<Vector3> pts = ListPool<Vector3>.Claim(count);
-
-
- float a = clearance/(2*Mathf.PI);
- float t = 0;
- pts.Add(InvoluteOfCircle(a, t));
- for (int i = 0; i < count; i++) {
- Vector3 prev = pts[pts.Count-1];
-
-
- float d = -t/2 + Mathf.Sqrt(t*t/4 + 2*clearance/a);
-
- float mn = t + d;
- float mx = t + 2*d;
- while (mx - mn > 0.01f) {
- float mid = (mn + mx)/2;
- Vector3 p = InvoluteOfCircle(a, mid);
- if ((p - prev).sqrMagnitude < clearance*clearance) {
- mn = mid;
- } else {
- mx = mid;
- }
- }
- pts.Add(InvoluteOfCircle(a, mx));
- t = mx;
- }
- return pts;
- }
-
-
-
-
- private static Vector3 InvoluteOfCircle (float a, float t) {
- return new Vector3(a*(Mathf.Cos(t) + t*Mathf.Sin(t)), 0, a*(Mathf.Sin(t) - t*Mathf.Cos(t)));
- }
-
-
-
-
-
-
-
-
-
-
-
-
- public static void GetPointsAroundPointWorld (Vector3 p, IRaycastableGraph g, List<Vector3> previousPoints, float radius, float clearanceRadius) {
- if (previousPoints.Count == 0) return;
- Vector3 avg = Vector3.zero;
- for (int i = 0; i < previousPoints.Count; i++) avg += previousPoints[i];
- avg /= previousPoints.Count;
- for (int i = 0; i < previousPoints.Count; i++) previousPoints[i] -= avg;
- GetPointsAroundPoint(p, g, previousPoints, radius, clearanceRadius);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static void GetPointsAroundPoint (Vector3 center, IRaycastableGraph g, List<Vector3> previousPoints, float radius, float clearanceRadius) {
- if (g == null) throw new System.ArgumentNullException("g");
- var graph = g as NavGraph;
- if (graph == null) throw new System.ArgumentException("g is not a NavGraph");
- NNInfoInternal nn = graph.GetNearestForce(center, NNConstraint.Default);
- center = nn.clampedPosition;
- if (nn.node == null) {
-
- return;
- }
-
- radius = Mathf.Max(radius, 1.4142f*clearanceRadius*Mathf.Sqrt(previousPoints.Count));
- clearanceRadius *= clearanceRadius;
- for (int i = 0; i < previousPoints.Count; i++) {
- Vector3 dir = previousPoints[i];
- float magn = dir.magnitude;
- if (magn > 0) dir /= magn;
- float newMagn = radius;
- dir *= newMagn;
- GraphHitInfo hit;
- int tests = 0;
- while (true) {
- Vector3 pt = center + dir;
- if (g.Linecast(center, pt, out hit)) {
- if (hit.point == Vector3.zero) {
-
-
-
- tests++;
- if (tests > 8) {
- previousPoints[i] = pt;
- break;
- }
- } else {
- pt = hit.point;
- }
- }
- bool worked = false;
- for (float q = 0.1f; q <= 1.0f; q += 0.05f) {
- Vector3 qt = Vector3.Lerp(center, pt, q);
- worked = true;
- for (int j = 0; j < i; j++) {
- if ((previousPoints[j] - qt).sqrMagnitude < clearanceRadius) {
- worked = false;
- break;
- }
- }
-
- if (worked || tests > 8) {
- worked = true;
- previousPoints[i] = qt;
- break;
- }
- }
-
- if (worked) {
- break;
- }
-
-
- clearanceRadius *= 0.9f;
-
- dir = Random.onUnitSphere * Mathf.Lerp(newMagn, radius, tests / 5);
- dir.y = 0;
- tests++;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- public static List<Vector3> GetPointsOnNodes (List<GraphNode> nodes, int count, float clearanceRadius = 0) {
- if (nodes == null) throw new System.ArgumentNullException("nodes");
- if (nodes.Count == 0) throw new System.ArgumentException("no nodes passed");
- List<Vector3> pts = ListPool<Vector3>.Claim(count);
-
- clearanceRadius *= clearanceRadius;
- if (clearanceRadius > 0 || nodes[0] is TriangleMeshNode
- #if !ASTAR_NO_GRID_GRAPH
- || nodes[0] is GridNode
- #endif
- ) {
-
- List<float> accs = ListPool<float>.Claim(nodes.Count);
-
- float tot = 0;
- for (int i = 0; i < nodes.Count; i++) {
- var surfaceArea = nodes[i].SurfaceArea();
-
-
- surfaceArea += 0.001f;
- tot += surfaceArea;
- accs.Add(tot);
- }
- for (int i = 0; i < count; i++) {
-
- int testCount = 0;
- int testLimit = 10;
- bool worked = false;
- while (!worked) {
- worked = true;
-
- if (testCount >= testLimit) {
-
- clearanceRadius *= 0.9f*0.9f;
- testLimit += 10;
- if (testLimit > 100) clearanceRadius = 0;
- }
-
- float tg = Random.value*tot;
- int v = accs.BinarySearch(tg);
- if (v < 0) v = ~v;
- if (v >= nodes.Count) {
-
- worked = false;
- continue;
- }
- var node = nodes[v];
- var p = node.RandomPointOnSurface();
-
- if (clearanceRadius > 0) {
- for (int j = 0; j < pts.Count; j++) {
- if ((pts[j]-p).sqrMagnitude < clearanceRadius) {
- worked = false;
- break;
- }
- }
- }
- if (worked) {
- pts.Add(p);
- break;
- }
- testCount++;
- }
- }
- ListPool<float>.Release(ref accs);
- } else {
-
- for (int i = 0; i < count; i++) {
- pts.Add((Vector3)nodes[Random.Range(0, nodes.Count)].RandomPointOnSurface());
- }
- }
- return pts;
- }
- }
- }
|