Pathfinding.PathUtilities.GetPointsOnNodes C# (CSharp) Method

GetPointsOnNodes() public static method

public static GetPointsOnNodes ( List nodes, int count, float clearanceRadius ) : List
nodes List
count int
clearanceRadius float
return List
		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");
			
			System.Random rnd = new System.Random();
			
			List<Vector3> pts = Pathfinding.Util.ListPool<Vector3>.Claim(count);
			
			// Square
			clearanceRadius *= clearanceRadius;
			
			if (nodes[0] is TriangleMeshNode || nodes[0] is GridNode) {
				//Assume all nodes are triangle nodes or grid nodes
				
				List<float> accs = Pathfinding.Util.ListPool<float>.Claim(nodes.Count);
					
				float tot = 0;
				
				for (int i=0;i<nodes.Count;i++) {
					TriangleMeshNode tnode = nodes[i] as TriangleMeshNode;
					if (tnode != null) {
						float a = System.Math.Abs(Polygon.TriangleArea(tnode.GetVertex(0), tnode.GetVertex(1), tnode.GetVertex(2)));
						tot += a;
						accs.Add (tot);
					} else {
						GridNode gnode = nodes[i] as GridNode;
						
						if (gnode != null) {
							GridGraph gg = GridNode.GetGridGraph (gnode.GraphIndex);
							float a = gg.nodeSize*gg.nodeSize;
							tot += a;
							accs.Add (tot);
						} else {
							accs.Add(tot);
						}
					}
				}
				
				for (int i=0;i<count;i++) {
					
					//Pick point
					int testCount = 0;
					int testLimit = 10;
					bool worked = false;
					
					while (!worked) {
						worked = true;
						
						//If no valid points can be found, progressively lower the clearance radius until such a point is found
						if (testCount >= testLimit) {
							clearanceRadius *= 0.8f;
							testLimit += 10;
							if (testLimit > 100) clearanceRadius = 0;
						}
					
						float tg = (float)rnd.NextDouble()*tot;
						int v = accs.BinarySearch(tg);
						if (v < 0) v = ~v;
						
						if (v >= nodes.Count) {
							// This shouldn't happen, due to NextDouble being smaller than 1... but I don't trust floating point arithmetic.
							worked = false;
							continue;
						}
						
						TriangleMeshNode node = nodes[v] as TriangleMeshNode;
						
						Vector3 p;
						
						if (node != null) {
							// Find a random point inside the triangle
							float v1;
							float v2;
							do {
								v1 = (float)rnd.NextDouble();
								v2 = (float)rnd.NextDouble();
							} while (v1+v2 > 1);
							
							p = ((Vector3)(node.GetVertex(1)-node.GetVertex(0)))*v1 + ((Vector3)(node.GetVertex(2)-node.GetVertex(0)))*v2 + (Vector3)node.GetVertex(0);
						} else {
							GridNode gnode = nodes[v] as GridNode;
							
							if (gnode != null) {
								GridGraph gg = GridNode.GetGridGraph (gnode.GraphIndex);
								
								float v1 = (float)rnd.NextDouble();
								float v2 = (float)rnd.NextDouble();
								p = (Vector3)gnode.position + new Vector3(v1 - 0.5f, 0, v2 - 0.5f) * gg.nodeSize;
							} else {
								//Point nodes have no area, so we break directly instead
								pts.Add ((Vector3)nodes[v].position);
								break;
							}
						}
						
						// Test if it is some distance away from the other points
						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;
						} else {
							testCount++;
						}
					}
				}
				
				Pathfinding.Util.ListPool<float>.Release(accs);
				
			} else {
				for (int i=0;i<count;i++) {
					pts.Add ((Vector3)nodes[rnd.Next (nodes.Count)].position);
				}
			}
			
			return pts;
		}
	}