/// <summary> /// Clears all the relevant status for this voxel /// </summary> public void ClearStatus() { IsOccupied = false; InSpace = false; ParentSpace = null; Part = null; }
/// <summary> /// Gets the space that the Arrow object represents /// </summary> /// <returns>The PPSpace object</returns> PPSpace GetSpaceFromArrow() { //This method allows clicking on the InfoArrow //and returns its respective space PPSpace clicked = null; Ray ClickRay = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ClickRay, out hit)) { if (hit.collider.gameObject.transform != null && hit.collider.gameObject.tag == "InfoArrow") { clicked = hit.collider.gameObject.GetComponent <InfoArrow>().GetSpace(); //print($"Clicked on {clicked.Name}'s arrow"); _showSpaceData = true; _spaceData = clicked.GetSpaceDebugInfo(); _cameraPivot.position = hit.collider.gameObject.transform.position; _selectedSpace = clicked; } } else { _spaceData = null; _selectedSpace = null; _showSpaceData = false; _cameraPivot.position = new Vector3(_gridSize.x / 2, 0, _gridSize.z / 2) * _voxelSize; } return(clicked); }
public void ReleaseIcon() { OnSpace = null; _userIcon.GetComponent <UserIcon>().ReleaseSpace(); SetGOVisibility(false); _userIcon.transform.position = Vector3.zero; }
/// <summary> /// Sets one of the existing spaces to be reconfigured /// </summary> protected virtual void SetRandomSpaceToReconfigure(int areaDirection, int connectivityDirection) { PPSpace space = new PPSpace(); bool validRequest = false; while (!validRequest) { UnityEngine.Random.InitState(System.DateTime.Now.Millisecond); int i = UnityEngine.Random.Range(0, _spaces.Count); space = _spaces[i]; if (space.BoundaryParts.Count > 0 && !space.IsSpare) { validRequest = true; } } //Set area to be increased ReconfigurationRequest rr = new ReconfigurationRequest(space, areaDirection, connectivityDirection); _reconfigurationRequests = new List <ReconfigurationRequest>(); _reconfigurationRequests.Add(rr); //Start requesting the first action //rr.RequestNextAction(); }
/// <summary> /// Gets the space that the Arrow object represents by clicking on the InfoArrow /// </summary> /// <returns>The <see cref="PPSpace"/> object</returns> protected virtual PPSpace GetSpaceFromArrow() { PPSpace clicked = null; Ray ClickRay = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ClickRay, out hit)) { if (hit.collider.gameObject.transform != null && hit.collider.gameObject.tag == "InfoArrow") { clicked = hit.collider.gameObject.GetComponent <InfoArrow>().GetSpace(); _showSpaceData = true; _spaceData = clicked.GetSpaceDebugInfo(); _cameraPivot.position = hit.collider.gameObject.transform.position; _selectedSpace = clicked; } } else { _spaceData = null; _selectedSpace = null; _showSpaceData = false; _cameraPivot.position = new Vector3(_gridSize.x / 2, 0, _gridSize.z / 2) * _voxelSize; } return(clicked); }
/// <summary> /// Manages the probabilistic simulation of Tenants requesting spaces /// </summary> /// <param name="request"></param> protected override void RequestSpace(PPSpaceRequest request) { var requestArea = request.Population * request.Tenant.AreaPerIndInferred; //Request area assuming the area the tenant prefers per individual var availableSpaces = _spaces.Where(s => !s.Occupied && !s.IsSpare); if (availableSpaces.Count() > 0) { PPSpace bestSuited = availableSpaces.MaxBy(s => s.Area); foreach (var space in availableSpaces) { var spaceArea = space.Area; if (spaceArea >= requestArea && spaceArea < bestSuited.Area) { bestSuited = space; } } bestSuited.OccupySpace(request); //string newMessage = $"Assinged {bestSuited.Name} to {request.Tenant.Name} at {_hour.ToString("D2")}:00 for {request.ActivityName}"; string newMessage = $"Assinged to {request.Tenant.Name}"; _spacesMessages[bestSuited] = newMessage; //AddDisplayMessage(newMessage); } else { //AddDisplayMessage("No available space found"); } }
public PPSpace MoveToSpace(PPSpace target) { target.Voxels.Add(this); this.ParentSpace.Voxels.Remove(this); this.ParentSpace = target; return(target); }
/// <summary> /// Runs the Pix2pix analysis on the current state of the grid, while /// updating the spaces that can be understood as the same /// </summary> public void RunAnalysisUpdateSpaces() { //Stopwatch aiStopwatch = new Stopwatch(); //aiStopwatch.Start(); //Copy the existing spaces List <PPSpace> existingSpaces = new List <PPSpace>(Spaces); //Copy the existing indices List <HashSet <Vector3Int> > existingIndices = new List <HashSet <Vector3Int> >(); foreach (var space in Spaces) { HashSet <Vector3Int> temp = new HashSet <Vector3Int>(); foreach (var index in space.Indices) { temp.Add(new Vector3Int(index.x, index.y, index.z)); } existingIndices.Add(temp); } //Generate new spaces Boundaries = new List <Voxel>(); var gridImage = GetStateImage256(); var analysisResult = _pix2pix.GeneratePrediction(gridImage); var resultTexture = ProcessAnalysisResult(analysisResult); PassBoundaryToList(resultTexture); List <PPSpace> newSpaces = GenerateSpaces(); List <PPSpace> resultSpaces = new List <PPSpace>(); //Compare new spaces with existing spaces foreach (var nSpace in newSpaces) { PPSpace outSpace = nSpace; for (int i = 0; i < existingSpaces.Count; i++) { var eSpace = existingSpaces[i]; var eIndices = existingIndices[i]; if (nSpace.CompareSpaces(eSpace, eIndices)) { //The existing space parameters should be evaluated here //nSpace.Name = "Existing"; nSpace.CopyDataFromSpace(eSpace); //existingSpaces.Remove(eSpace); break; } } } Spaces = newSpaces; SetSpacesToConfigurableParts(); //aiStopwatch.Stop(); //var t = aiStopwatch.ElapsedMilliseconds; //print($"Took {t} ms to update"); }
public static void DrawSpaceSurface(PPSpace space, VoxelGrid grid, Color color, Vector3 origin) { var voxelSize = grid.VoxelSize; _properties.SetColor("_BaseColor", color); var indices = space.Indices; foreach (var index in indices) { Vector3 position = ((index + new Vector3(0.5f, 1.1f, 0.5f)) * voxelSize) + origin; DrawFace(position, Axis.Y, voxelSize, color); } }
/// <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> /// Checks if the reconfiguration subject of a request is still valid or has been destroyed /// </summary> /// <param name="request">The request to be assessed</param> /// <returns>An integer representing the result of the action /// 0 = valid; /// 1 = successful; /// 2 = destroyed the space</returns> public int CheckResultFromRequest(ReconfigurationRequest request) { int result = 1; Guid spaceId = request.SpaceId; int checkCount = _spaces.Count(s => s.SpaceId == spaceId); if (checkCount == 1) { PPSpace space = MainGrid.GetSpaceById(spaceId); if (space != null) { //Space still exists, evaluate if reconfiguration was successful bool success = request.ReconfigurationSuccessful(space); request.CurrentIndices = space.Indices.ToArray(); if (success) { _reconfigurationRequests.Remove(request); } else { result = 0; } space.Reconfigure_Area = false; space.Reconfigure_Connectivity = false; _reconfigurationRequests.Remove(request); } } else if (checkCount > 1) { //Space was destroyed and split into 2 or more. Differentiate new spaces foreach (var space in _spaces.Where(s => s.SpaceId == spaceId)) { space.SpaceId = Guid.NewGuid(); space.Reconfigure_Area = false; space.Reconfigure_Connectivity = false; } _reconfigurationRequests.Remove(request); result = 2; } else { //Space was destroyed, return false _reconfigurationRequests.Remove(request); result = 2; } return(result); }
public static List <PPSpace> ReadSpacesAsList(VoxelGrid grid, string file) { List <PPSpace> outList = new List <PPSpace>(); string jsonString = Resources.Load <TextAsset>(file).text; PPSpaceCollection spaceList = JsonUtility.FromJson <PPSpaceCollection>(jsonString); int count = 0; foreach (var space in spaceList.Spaces) { PPSpace s = new PPSpace(); s.OCIndexes = space.OCIndexes; outList.Add(s.NewSpace(grid, $"Space_{count++}")); } return(outList); }
public static void DrawSpaceBoundary(PPSpace space, VoxelGrid grid, Color color, Vector3 origin) { var voxelSize = grid.VoxelSize; _properties.SetColor("_BaseColor", color); var boundary = space.SortedBoundaryIndexes; for (int i = 0; i < boundary.Length; i++) { Vector3 start = boundary[i]; Vector3 end; if (i + 1 >= boundary.Length) end = boundary[0]; else end = boundary[i + 1]; start = ((start + new Vector3(0.5f, 1.5f, 0.5f)) * voxelSize) + origin; end = ((end + new Vector3(0.5f, 1.5f, 0.5f)) * voxelSize) + origin; DrawBar(start, end, 0.05f, color); } }
void RequestSpace(PPSpaceRequest request) { var requestArea = request.Population * 8; //This considers that 1 person requires 8 voxels (~1m²) var availableSpaces = _spaces.Where(s => !s.Occupied && !s.IsSpare); PPSpace bestSuited = availableSpaces.MaxBy(s => s.Area); foreach (var space in availableSpaces) { var spaceArea = space.Area; if (spaceArea >= requestArea && spaceArea < bestSuited.Area) { bestSuited = space; } } bestSuited.OccupySpace(request); print($"Assinged {bestSuited.Name} to {request.Tenant.Name} at {_dateTimeNow}"); }
//public static void DrawSpacesColour(List<PPSpace> spaces, VoxelGrid grid) //{ // var voxelSize = grid.VoxelSize; // for (int i = 0; i < spaces.Count; i++) // { // UnityEngine.Random.InitState(i); // float r = UnityEngine.Random.value; // UnityEngine.Random.InitState(2*i); // float g = UnityEngine.Random.value; // UnityEngine.Random.InitState(3*i); // float b = UnityEngine.Random.value; // var color = new Color(r, g, b, 0.70f); // _properties.SetColor("_Color", color); // var space = spaces[i]; // foreach (var voxel in space.Voxels) // { // var center = voxel.Center + (Vector3.up*voxelSize); // var matrix = Matrix4x4.TRS( // center, // Quaternion.identity, // Vector3.one * (voxelSize * 0.99f) // ); // Graphics.DrawMesh(_unitBox, matrix, _instance._transparent, 0, null, 0, _properties); // } // } //} public static void DrawSpace(PPSpace space, VoxelGrid grid, Color color, Vector3 origin) { var voxelSize = grid.VoxelSize; _properties.SetColor("_BaseColor", color); foreach (var voxel in space.Voxels) { Vector3 index = origin + (new Vector3(voxel.Index.x + 0.5f, voxel.Index.y + 0.5f, voxel.Index.z + 0.5f) * voxelSize); var center = index + (Vector3.up * voxelSize); var matrix = Matrix4x4.TRS( center, Quaternion.identity, Vector3.one * (voxelSize * 0.3f) ); Graphics.DrawMesh(_unitBox, matrix, _instance._transparent, 0, null, 0, _properties); } }
/// <summary> /// Attempts to assign a space to a request made by a Tenant /// </summary> /// <param name="request">The Request object</param> void RequestSpace(PPSpaceRequest request) { var requestArea = request.Population * request.Tenant.AreaPerIndInferred; //Request area assuming the area the tenant prefers per individual var availableSpaces = _spaces.Where(s => !s.Occupied && !s.IsSpare); PPSpace bestSuited = availableSpaces.MaxBy(s => s.VoxelCount); foreach (var space in availableSpaces) { var spaceArea = space.Area; if (spaceArea >= requestArea && spaceArea < bestSuited.VoxelCount) { bestSuited = space; } } bestSuited.OccupySpace(request); _activityLog = $"Assinged {bestSuited.Name} to {request.Tenant.Name} at {_dateTimeNow}"; }
/// <summary> /// Checks if the reconfiguration has been successful /// </summary> /// <param name="space">The space to be checked</param> /// <returns>The result if the reconfiguration was successful</returns> public bool ReconfigurationSuccessful(PPSpace space) { //Get the current parameters [area = Voxel count; connectivity = number of connections] int currentArea = space.VoxelCount; int currentConnectivity = space.NumberOfConnections; //Create the result validators, starting with true bool areaSuccessful = true; bool connectivitySuccessful = true; //Check if reconfiguration was successful, within a margin of +- 50% of the target parameter //Check if area objective has been reached [0 = no area reconfiguration requested] if (TargetArea != 0) { if (currentArea < TargetArea - (_areaModifier / 2) || currentArea > TargetArea + (_areaModifier / 2)) { areaSuccessful = false; } } //Check if connectivity objective has been reached [0 = no connectivity reconfiguration requested] if (TargetConnections != 0) { if (currentConnectivity < TargetConnections - (_connectivityModifier / 2) || currentConnectivity > TargetConnections + (_connectivityModifier / 2)) { connectivitySuccessful = false; } } //Check if the request has been fullfiled if (areaSuccessful && connectivitySuccessful) { //OnReconfigurationSuccessful(); return(true); } else { //UnfreezeRandomAgent(); return(false); } }
/// <summary> /// Manages the probabilistic simulation of Tenants requesting spaces /// </summary> /// <param name="request"></param> protected override void RequestSpace(PPSpaceRequest request) { var requestArea = request.Population * request.Tenant.AreaPerIndInferred; //Request area assuming the area the tenant prefers per individual var availableSpaces = _spaces.Where(s => !s.Occupied && !s.IsSpare); if (availableSpaces.Count() > 0) { PPSpace bestSuited = availableSpaces.MaxBy(s => s.Area); foreach (var space in availableSpaces) { var spaceArea = space.Area; if (spaceArea >= requestArea && spaceArea < bestSuited.Area) { bestSuited = space; } } bestSuited.OccupySpace(request); string newMessage = $"Assinged to {request.Tenant.Name}"; _spacesMessages[bestSuited] = newMessage; } }
/// <summary> /// Sets one of the existing spaces to be reconfigured. /// This overriden method replaces the behaviour brain according to the type of request /// </summary> protected override void SetRandomSpaceToReconfigure(int areaDirection, int connectivityDirection) { PPSpace space = new PPSpace(); bool validRequest = false; while (!validRequest) { UnityEngine.Random.InitState(System.DateTime.Now.Millisecond); int i = UnityEngine.Random.Range(0, _spaces.Count); space = _spaces[i]; if (space.BoundaryParts.Count > 0 && !space.IsSpare) { validRequest = true; } } //Create the reconfiguration request ReconfigurationRequest rr = new ReconfigurationRequest(space, areaDirection, connectivityDirection); _reconfigurationRequests = new List <ReconfigurationRequest>(); _reconfigurationRequests.Add(rr); }
public static void DrawSpace(PPSpace space, VoxelGrid grid, Color color) { var voxelSize = grid.VoxelSize; //var color = new Color(0.9f, 0.9f, 0.9f, 0.70f); //if (selected) //{ // color = new Color(0.85f, 1.0f, 0.0f, 0.70f); //} _properties.SetColor("_Color", color); foreach (var voxel in space.Voxels) { var center = voxel.Center + (Vector3.up * voxelSize); var matrix = Matrix4x4.TRS( center, Quaternion.identity, Vector3.one * (voxelSize * 0.85f) ); Graphics.DrawMesh(_unitBox, matrix, _instance._transparent, 0, null, 0, _properties); } }
public void ReleaseSpace() { _space = null; }
/// <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> void GenerateSingleSpace(int number) { int maximumArea = 1000; //in voxel ammount var availableVoxels = _grid.ActiveVoxelsAsList().Where(v => !_boundaries.Contains(v) && !v.IsOccupied && !v.InSpace).ToList(); if (availableVoxels.Count == 0) { return; } Voxel originVoxel = availableVoxels[0]; //Initiate a new space PPSpace space = new PPSpace(_grid); 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 = _grid.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.CreateArrow(); _spaces.Add(space); }
/// <summary> /// Check if there are enough requests to initialize reconfiguration. If so, pauses simulation /// and tells the agents to store their current positions /// </summary> protected override void CheckForReconfiguration() { //If the space count (of non-spare spaces) is 0, restart the position of every other part if (_spaces.Where(s => !s.IsSpare).Count() == 1) { for (int i = 0; i < _agents.Count; i++) { if (i % 2 == 0) { ConfigurablePart part = _agents[i].GetPart(); int attempt = 0; bool success = false; foreach (var index in part.OccupiedIndexes) { var voxel = MainGrid.Voxels[index.x, index.y, index.z]; voxel.IsOccupied = false; voxel.Part = null; } while (!success) { part.JumpToNewPosition(PopSeed + attempt, out success); attempt++; } } } FinilizeReconfiguration(); _activeRequest = null; foreach (var agent in _agents) { agent.FreezeAgent(); agent.ClearRequest(); } ResetSpacesEvaluation(); } //If all ok, continue checking for reconfiguration else if (_spaces.Count(s => s.Reconfigure) > 0) { _timePause = true; //Get only the first one and only create one type of request. var toReconfigure = _spaces.Where(s => s.Reconfigure).ToList(); var target = toReconfigure[0]; if (target.Reconfigure_Area) { //SetAreaModel(); int targetArea = 1; if (target._areaDecrease > target._areaIncrease) { targetArea = -1; } ReconfigurationRequest rr = new ReconfigurationRequest(target, targetArea, 0); _activeRequest = rr; //_reconfigurationRequests.Add(rr); } else if (target.Reconfigure_Connectivity) { //SetConnectivityModel(); int targetConnec = 1; if (target._connectivityDecrease > target._connectivityIncrease) { targetConnec = -1; } ReconfigurationRequest rr = new ReconfigurationRequest(target, 0, targetConnec); _activeRequest = rr; //_reconfigurationRequests.Add(rr); } var spaces = _spaces.Where(s => s.Reconfigure).ToList(); for (int i = 1; i < _spaces.Count(s => s.Reconfigure); i++) { PPSpace space = spaces[i]; space.ResetAreaEvaluation(); space.ResetConnectivityEvaluation(); space.TimesSurvived = 0; space.TimesUsed = 0; } } }
public void SetSpaceToIcon(PPSpace space, VoxelGrid grid) { _userIcon.SetActive(true); _userIcon.GetComponent <UserIcon>().SetSpace(space, grid); //_userIcon.SetActive(true); }
public void SetSpace(PPSpace space) { _space = space; }
public void SetSpaceToIcon(PPSpace space, VoxelGrid grid) { SetGOVisibility(true); _userIcon.GetComponent <UserIcon>().SetSpace(space, grid); OnSpace = space; }
void GenerateSS_NAI(int number) { //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 Stopwatch singleSpace = new Stopwatch(); singleSpace.Start(); int maximumArea = 1000; //in voxel ammount var availableVoxels = _grid.ActiveVoxelsAsList().Where(v => !_boundaries.Contains(v) && !v.IsOccupied && !v.InSpace).ToList(); if (availableVoxels.Count == 0) { return; } Voxel originVoxel = availableVoxels[0]; //Initiate a new space PPSpace space = new PPSpace(_grid); 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 = _grid.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.CreateArrow(); _spaces.Add(space); //singleSpace.Stop(); //_singleSpaceTime = (int)singleSpace.ElapsedMilliseconds; }
public void SetSpace(PPSpace space, VoxelGrid grid) { _space = space; transform.position = _space.GetCenter() + (new Vector3(0, 1.5f, 0) * grid.VoxelSize); }