// Tries to create a horizontal region starting from the bottom-left of the area public static Region createRegionVertical(Region region) { region.sortTerminals(); int toY = -1; // Try to find a line starting from X = 'from' for (int i = 0; i < region.terminals.Count; i++) { Rectangle rect = region.terminals[i]; if (rect.fromX == region.fromX) { // We can start to draw a line from here Rectangle current = rect; bool nextRectangleExists = true; // While there exists a rectangle that can continue the line or we have reached the end while (nextRectangleExists && current.toX != region.toX) { nextRectangleExists = false; foreach (Rectangle next in region.terminals) { // If the rectangles are Y-aligned and are adjacent if (current != next && next.fromX - 1 == current.toX && next.toY == current.toY) { current = next; nextRectangleExists = true; break; } } } // If the generated line succesfully stretches from 'from' to 'to' then we have created a valid line and can end the loop if (current.toX == region.toX) { toY = current.toY; break; } } } if (toY == -1) { // Algorithm was unable to draw a horizontal line on the shape return(null); } List <Rectangle> areaTerminals = new List <Rectangle>(); // We now have a valid line of rectangles but would like to fill in the potential gaps of the area foreach (Rectangle rect in region.terminals) { // Add all regions below the line to our new area list if (rect.toY <= toY) { areaTerminals.Add(rect); } } return(new Region(areaTerminals)); }
// Reads in all information of a facade public List <Rectangle> initializeNewFacade(InputFacade facade) { allCurrentFacadeRectangles = RegionFinder.findRectangles(facade.facadeLayoutName, facade.inputFacade.width, facade.inputFacade.height); float maxY = 0; float maxX = 0; foreach (Color c in allCurrentFacadeRectangles.Keys) { foreach (Rectangle r in allCurrentFacadeRectangles[c]) { maxX = Mathf.Max(maxX, r.toX); maxY = Mathf.Max(maxY, r.toY); } } buildingNameText.text = facade.gameObject.name; widthText.text = facade.getBuildingWidth().ToString(); heightText.text = facade.getBuildingHeight().ToString(); Vector3 previewScale = facadePreview.rectTransform.localScale; facadePreview.rectTransform.localScale = new Vector3(previewScale.y * facade.getBuildingWidth() / facade.getBuildingHeight(), previewScale.y, 1); layoutPreview.rectTransform.localScale = facadePreview.rectTransform.localScale; foreach (Color c in allCurrentFacadeRectangles.Keys) { Rectangle newRect = new Rectangle(); newRect.symbol = c; currentFacadeRectangles.Enqueue(newRect); } return(null); }
// Updates all rectangles of one color private void updateRectangles(Rectangle infoR) { foreach (Rectangle toUpdate in allCurrentFacadeRectangles[infoR.symbol]) { toUpdate.depth = infoR.depth; toUpdate.name = infoR.name; } }
public Region(Rectangle rectangle) { fromX = rectangle.fromX; fromY = rectangle.fromY; toX = rectangle.toX; toY = rectangle.toY; terminals = new List <Rectangle>(); terminals.Add(rectangle); subregions = new List <Region>(); }
// Goes a step in the generation interface, choosing the next rectangle or going to the next facade public void updateNext() { Rectangle infoRect = new Rectangle(); infoRect.name = nameField.text; float.TryParse(zField.text, out infoRect.depth); infoRect.symbol = currentRectangle.symbol; informationRects.Add(infoRect); // Go to next rectangle nextRectangle(); updateInformationBox(currentRectangle); }
private static Texture2D cutFromFacade(Rectangle cutArea, Texture2D facade) { int width = cutArea.toX - cutArea.fromX; int height = cutArea.toY - cutArea.fromY; Texture2D cutTexture = new Texture2D(width, height); if (width == 0 || height == 0) { Debug.LogWarning("Nonvalid width/height of area. From (" + cutArea.fromX + "," + cutArea.fromY + ") - To: (" + cutArea.toX + "," + cutArea.toY + ")"); } cutTexture.SetPixels(facade.GetPixels(cutArea.fromX, cutArea.fromY, width, height)); return(cutTexture); }
// Clears all information of the current facade and initializes variables for the next // Returns true if there was a next facade, false if not private bool nextFacade() { nextFacadeIndex++; if (nextFacadeIndex <= facades.Length) { // Clear all information informationRects = new List <Rectangle>(); currentFacadeRectangles = new Queue <Rectangle>(); currentRectangle = null; // Initialize the new facade InputFacade iF = facades[nextFacadeIndex - 1].GetComponent <InputFacade>(); initializeNewFacade(iF); Texture2D layoutTex = readFacadeImage(Application.dataPath + iF.facadeLayoutName); facadePreview.sprite = Sprite.Create(iF.inputFacade, new Rect(0, 0, iF.inputFacade.width, iF.inputFacade.height), facadePreview.sprite.pivot); layoutPreview.sprite = Sprite.Create(layoutTex, new Rect(0, 0, layoutTex.width, layoutTex.height), facadePreview.sprite.pivot); // Go to the next facade index return(true); } return(false); }
// Chooses the next rectangle and invokes rule generation if it is the last one private void nextRectangle() { // If we should proceed to the next rectangle if (currentFacadeRectangles.Count <= 0) { // Update all rectangles with our given information foreach (Rectangle infoR in informationRects) { updateRectangles(infoR); } // Start generation from the given rectangles ruleGen.beginGeneration(allCurrentFacadeRectangles, facades[nextFacadeIndex - 1].GetComponent <InputFacade>(), fileDS); fileDS.WriteLine(); fileDS.Flush(); if (!nextFacade()) { return; } } currentRectangle = currentFacadeRectangles.Dequeue(); }
// Sorts the terminal regions according to their position // From lowest X, if X1=X2 then look at Y public void sortTerminals() { List <Rectangle> sortedList = new List <Rectangle>(); foreach (Rectangle toInsert in terminals) { if (sortedList.Count == 0) { sortedList.Add(toInsert); } else { // If it's the smallest element if (toInsert.fromX < sortedList[0].fromX || (toInsert.fromX == sortedList[0].fromX && toInsert.fromY < sortedList[0].fromY)) { sortedList.Insert(0, toInsert); } else if (toInsert.fromX > sortedList[sortedList.Count - 1].fromX || (toInsert.fromX == sortedList[sortedList.Count - 1].fromX && toInsert.fromY > sortedList[sortedList.Count - 1].fromY)) { sortedList.Add(toInsert); } else { // Go through all elements until it is the biggest for (int i = 0; i < sortedList.Count; i++) { Rectangle other = sortedList[i]; if (toInsert.fromX < other.fromX || (toInsert.fromX == other.fromX && toInsert.fromY < other.fromY)) { sortedList.Insert(i, toInsert); break; } } } } } terminals = sortedList; }
public static Dictionary <Color, List <Rectangle> > findRectangles(string terminalRegionsName, int width, int height) { byte[] bytes = File.ReadAllBytes(Application.dataPath + terminalRegionsName); Texture2D image = new Texture2D(width, height); image.LoadImage(bytes); bool[,] visited = new bool[image.width, image.height]; Dictionary <Color, List <Rectangle> > rectangles = new Dictionary <Color, List <Rectangle> >(); for (int x = 0; x < image.width; x++) { for (int y = 0; y < image.height; y++) { if (!visited[x, y]) { Color c = image.GetPixel(x, y); if (!rectangles.ContainsKey(c)) { rectangles.Add(c, new List <Rectangle>()); } Rectangle newRec = new Rectangle(); newRec.fromX = x; newRec.fromY = y; newRec.symbol = c; int indexPointer = x; // While the color of the current pixel is equal to the rectangles color while (indexPointer < image.width && image.GetPixel(indexPointer, y) == c && !visited[indexPointer, y]) { indexPointer++; } newRec.toX = indexPointer - 1; int currentY = y + 1; indexPointer = x; while (currentY < image.height && image.GetPixel(indexPointer, currentY) == c && !visited[indexPointer, currentY]) { indexPointer++; if (indexPointer > newRec.toX) { indexPointer = x; currentY++; } } // -1 since the current color was evaluated to not be equal newRec.toY = currentY - 1; // Set all pixels of the rectangle to visited for (int vX = newRec.fromX; vX <= newRec.toX; vX++) { for (int vY = newRec.fromY; vY <= newRec.toY; vY++) { visited[vX, vY] = true; } } // Add the rectangle to list rectangles[c].Add(newRec); } } } return(rectangles); }
private void updateInformationBox(Rectangle rect) { nameField.text = ""; zField.text = ""; colorBox.GetComponent <Image>().color = rect.symbol; }