/// <summary> /// Constructor for a ReconfigurationRequest for a given space, with instructions for /// Area and Connectivity reconfiguration. /// [+1] = Increase /// [-1] = Decrese /// [0] = Don't change /// </summary> /// <param name="space">The space that should be reconfigured</param> /// <param name="areaDirection">The direction for the area reconfiguration</param> /// <param name="connectivityDirection"></param> public ReconfigurationRequest(PPSpace space, int areaDirection, int connectivityDirection) { space.ValidateSpace(); SpaceId = space.SpaceId; SpaceName = space.Name; _spaceCenter = new Vector3Int((int)space.GetCenter().x, 0, (int)space.GetCenter().z); CurrentIndices = space.Indices.ToArray(); //Area defined by the Voxel count int currentArea = space.VoxelCount; //Conectivity defined by the number of connections [voxels] int currentConnectivity = space.NumberOfConnections; space.ArtificialReconfigureRequest(areaDirection, connectivityDirection); //Set the target area if (areaDirection == 1) { TargetArea = currentArea + _areaModifier; } else if (areaDirection == -1) { TargetArea = currentArea - _areaModifier; } else if (areaDirection == 0) { TargetArea = 0; } //Set the target connections if (connectivityDirection == 1) { TargetConnections = currentConnectivity + _connectivityModifier; } else if (connectivityDirection == -1) { TargetConnections = currentConnectivity - _connectivityModifier; } else if (connectivityDirection == 0) { TargetConnections = 0; } _agents2Reconfigure = space.BoundaryParts.Select(p => p.CPAgent).ToArray(); foreach (var part in _agents2Reconfigure) { part.ClearRequest(); part.SetRequest(this); } //UnfreezeRandomAgent(); UnfreezeAgents(); }
/// <summary> /// Generate spaces on the voxels that are not inside the parts boudaries, or space or part /// The method is inspired by a BFS algorithm, continuously checking the neighbours of the /// processed voxels until the minimum area is reached. It is designed to be called in a loop /// that feeds the numbering / naming of the spaces /// </summary> /// <param name="number">Current number of the space</param> private PPSpace GenerateSingleSpace(int number, out bool result) { int maximumArea = 1000; //in voxel ammount var availableVoxels = ActiveVoxelsAsList().Where(v => !Boundaries.Contains(v) && !v.IsOccupied && !v.InSpace).ToList(); //Initiate a new space PPSpace space = new PPSpace(this); result = true; if (availableVoxels.Count == 0) { result = false; return(space); } Voxel originVoxel = availableVoxels[0]; originVoxel.InSpace = true; originVoxel.ParentSpace = space; space.Voxels.Add(originVoxel); space.Indices.Add(originVoxel.Index); //Keep running until the space area is under the minimum while (space.Voxels.Count < maximumArea) { List <Voxel> temp = new List <Voxel>(); foreach (var voxel in space.Voxels) { //Get the face neighbours which are available var newNeighbours = voxel.GetFaceNeighbours().Where(n => availableVoxels.Contains(n)); foreach (var neighbour in newNeighbours) { var nIndex = neighbour.Index; var gridVoxel = Voxels[nIndex.x, nIndex.y, nIndex.z]; //Only add the nighbour it its not already in the space //or temp list, is active, not occupied(in a part), or another space if (!space.Voxels.Contains(neighbour) && !temp.Contains(neighbour)) { if (gridVoxel.IsActive && !gridVoxel.IsOccupied && !gridVoxel.InSpace) { temp.Add(neighbour); } } } } //Break if the temp list returned empty if (temp.Count == 0) { break; } //Add found neighbours to the space until it reaches maximum capacity foreach (var v in temp) { if (space.Voxels.Count <= maximumArea) { v.InSpace = true; v.ParentSpace = space; space.Voxels.Add(v); space.Indices.Add(v.Index); } } } space.Name = $"Space_{number.ToString()}"; space.ValidateSpace(); return(space); //Spaces.Add(space); }