/// <summary> /// At a resolution determined by <paramref name="gridSize"/>, determine the relative traffic of all areas in the experiment. /// </summary> /// <param name="gridSize">The width and height of the grid the experiment should be superimposed upon.</param> /// <param name="maxTime">The amount of seconds within the simulation to include when making the grid (up until the end of the simluation)</param> /// <param name="mode">The type of mapping to perform between vertices on the grid and the bots</param> /// <returns>Traffic grid</returns> /// <remarks> /// Weighted at 1 unit of weight per second. /// </remarks> protected Tuple <float[][], float[][][]> ProjectBoidsToGrid(int gridSize = 21, float maxTime = float.PositiveInfinity, MappingMode mode = MappingMode.SAME_QUAD) { // Initialization float[][] trafficGrid = new float[gridSize][]; float[][][] pathGrid = new float[gridSize][][]; float[][] weightGrid = new float[gridSize][]; for (int row = 0; row < gridSize; row++) { trafficGrid[row] = new float[gridSize]; pathGrid[row] = new float[gridSize][]; weightGrid[row] = new float[gridSize]; for (int col = 0; col < gridSize; col++) { trafficGrid[row][col] = 0; float[] zeroVector = { 0, 0, 0 }; pathGrid[row][col] = zeroVector; weightGrid[row][col] = 0; } } if (mode == MappingMode.SAME_QUAD) { // Add weights for (int i = 0; i < Current.Count - 1; i++) { BoidsSnapshot snapshot = Current[i]; if (snapshot.Timestamp < maxTime) // Since the list is not garunteed to be sorted, we can't break when we pass the max time. { for (int j = 0; j < snapshot.Coords.Count; j++) { float[] coord = snapshot.Coords[j]; float[] direction = { Current[i + 1].Coords[j][0] - snapshot.Coords[j][0], // x Current[i + 1].Coords[j][1] - snapshot.Coords[j][1], // y 0 // z }; DistributeBoidWeightOverQuad(ref trafficGrid, ref pathGrid, coord, direction, ref weightGrid, DeltaTime[i]); } } } // Special case for last snapshot; no next vector direction, so vector must be either considered zero or set to the last vector for that boid. BoidsSnapshot lastSnapshot = Current[Current.Count - 1]; if (lastSnapshot.Timestamp < maxTime) { for (int j = 0; j < lastSnapshot.Coords.Count; j++) { float[] coord = lastSnapshot.Coords[j]; float[] direction = { 0, 0, 0 }; DistributeBoidWeightOverQuad(ref trafficGrid, ref pathGrid, coord, direction, ref weightGrid, DeltaTime[Current.Count - 1]); } } } else if (mode == MappingMode.ALL_QUAD) { throw new System.NotImplementedException("Mapping mode not supported: All quads."); } return(new Tuple <float[][], float[][][]>(trafficGrid, pathGrid)); }
/// <summary> /// Initializes the boids experiment from a serialized representation. /// </summary> /// <remarks> /// Instead of using the convenience function, the beginning of a proper setup would look something like: /// FileStream input = File.OpenRead(inputFile); /// Span<byte> inputBuffer; // Alternative consideration if this were a more serious project. /// </remarks> /// <param name="snapshotsRaw">A serialized representation of the snapshot conforming to <see href="https://regex101.com/r/2eIGmk/6/"/>. May have multiple lines.</param> protected void InitializeSnapshots(string[] snapshotsRaw) { Current = new List <BoidsSnapshot>(); // Reads the snapshot as a whole. Regex snapshotReader = new Regex(@"(?<time>[\d\.,\-]+):(?:(?:-?[\d,\.]+);(?:-?[\d,\.]+)#)*", RegexOptions.Compiled | RegexOptions.IgnoreCase); // Reads each ordered pair in the snapshot. Regex orderedPairFinder = new Regex(@"(?<coordx>-?[\d,\.]+);(?<coordy>-?[\d,\.]+)#", RegexOptions.Compiled | RegexOptions.IgnoreCase); for (int i = 0; i < snapshotsRaw.Length; i++) { // For each snapshot // Clean up erronious parts of the lines (no idea how those got there): // Get the overallsnapshat data. if (snapshotsRaw.Equals("") && i == snapshotsRaw.Length - 1) { return; // Allow blank line at EOF. } Match parsedSnapshot = snapshotReader.Match(snapshotsRaw[i]); if (!parsedSnapshot.Success) { string err = "Could not interpret line " + i + " of input."; Console.WriteLine(err); throw new ArgumentException(err); } float t = float.Parse(parsedSnapshot.Groups["time"].Value); // Get snapshot data for each boid. List <float[]> pairs = new List <float[]>(); MatchCollection rawPairs = orderedPairFinder.Matches(snapshotsRaw[i]); for (int j = 0; j < rawPairs.Count; j++) { Match currentPair = rawPairs[j]; float[] parsedPair = { float.Parse(currentPair.Groups["coordx"].Value), float.Parse(currentPair.Groups["coordy"].Value) }; pairs.Add(parsedPair); } // Save the snapshot BoidsSnapshot s = new BoidsSnapshot(t, pairs); Current.Add(s); } }
private void InitializeBounds(float margin = 0.1f) { if (Current.Count == 0 || Current[0].Coords.Count == 0) { return; // Can't calculate bounds on an empty experiment } BoidsSnapshot firstSnapshot = Current[0]; bounds = new float[] { firstSnapshot.Coords[0][0] - margin, firstSnapshot.Coords[0][1] - margin, firstSnapshot.Coords[0][0] + margin, firstSnapshot.Coords[0][1] + margin }; for (int i = 0; i < Current.Count; i++) { BoidsSnapshot s = Current[i]; for (int j = 0; j < s.Coords.Count; j++) { float[] c = s.Coords[j]; if (c[0] - margin < bounds[0]) { bounds[0] = c[0] - margin; } if (c[1] - margin < bounds[1]) { bounds[1] = c[1] - margin; } if (c[0] + margin > bounds[2]) { bounds[2] = c[0] + margin; } if (c[1] + margin > bounds[3]) { bounds[3] = c[1] + margin; } } } //throw new System.NotImplementedException(); }