public void Initialize(char symbol, int index, ArchitectureStyle style) { if (symbol == 'e') { return; } IResultSet resultSet = Repository.List("facade_item").Filter("style", style.name).Filter("symbol", symbol + "").Filter("index", index + ""); if (resultSet.Count() == 0) { throw new Exception("model not found (style: " + style.name + ", element: " + symbol + index + ")"); } _model = resultSet.Get(0); if (_model == null) { throw new Exception("invalid model (style: " + style.name + ", element: " + symbol + index + ")"); } CacheMetadata(); _invalid = false; }
static Pattern <T> ParsePattern <T> (string patternString, ArchitectureStyle architectureStyle) where T : IPatternItem, new() { StringReader reader = new StringReader(patternString); List <string> lines = new List <string> (); string line; while ((line = reader.ReadLine()) != null) { line = line.Trim(); if (line.Length == 0) { continue; } lines.Add(line); } int numberOfLines = lines.Count; int numberOfColumns = -1; Pattern <T> pattern = null; for (int y = 0; y < numberOfLines; y++) { string[] columns = Regex.Split(lines [y], @"\s+"); if (numberOfColumns == -1) { numberOfColumns = columns.Length; } else if (numberOfColumns != columns.Length) { throw new Exception("different column sizes in pattern matrix"); } if (pattern == null) { pattern = new Pattern <T> (numberOfColumns, numberOfLines, architectureStyle); } for (int x = 0; x < numberOfColumns; x++) { string elementString = columns [x]; if (elementString.Length < 2) { throw new Exception("invalid element: " + elementString); } char symbol = elementString [0]; int index = int.Parse(elementString.Substring(1)); pattern.SetElement(x, y, symbol, index); } } return(pattern); }
public Allotment(int x, int y, int width, int depth, int widthInTiles, int depthInTiles, Direction[] freeFaces, ArchitectureStyle architectureStyle) { this.x = x; this.y = y; this.width = width; this.depth = depth; this.widthInTiles = widthInTiles; this.depthInTiles = depthInTiles; this.freeFaces = freeFaces; this.architectureStyle = architectureStyle; }
public Pattern(int width, int height, ArchitectureStyle architectureStyle) { _width = width; _height = height; _items = new T[_height][]; _architectureStyle = architectureStyle; for (int i = 0; i < _height; i++) { _items [i] = new T[_width]; } }
public Facade(Direction direction, int width, int height, int widthInTiles, int heightInTiles, ArchitectureStyle architecturalStyle, Pattern <FacadeItem> elementsPattern, Pattern <FacadeItem> detailsPattern, Pattern <FacadeOperation> operationsPattern) { this.direction = direction; this.width = width; this.height = height; this.widthInTiles = widthInTiles; this.heightInTiles = heightInTiles; this.architectureStyle = architecturalStyle; this.elementsPattern = elementsPattern; this.detailsPattern = detailsPattern; this.operationsPattern = operationsPattern; }
public override void Execute(List <Allotment> allotments) { _buildings = new List <Building> (); foreach (Allotment allotment in allotments) { ArchitectureStyle architectureStyle = allotment.architectureStyle; int heightInTiles = UnityEngine.Random.Range(architectureStyle.minHeight, architectureStyle.maxHeight + 1); int height = heightInTiles * architectureStyle.tileHeight; int widthInTiles = allotment.widthInTiles - architectureStyle.spacing; int width = widthInTiles * architectureStyle.tileWidth; int depthInTiles = allotment.depthInTiles - architectureStyle.spacing; int depth = depthInTiles * architectureStyle.tileWidth; Facade[] facades = new Facade[allotment.freeFaces.Length]; int i = 0; foreach (Direction freeFace in allotment.freeFaces) { int longitude; int longitudeInTiles; if (freeFace == Direction.BACK || freeFace == Direction.FRONT) { longitude = width; longitudeInTiles = widthInTiles; } else { longitude = depth; longitudeInTiles = depthInTiles; } Pattern <FacadeItem> elementsPattern = architectureStyle.randomElementsPattern.Stretch(longitudeInTiles, heightInTiles); Pattern <FacadeItem> detailsPattern = architectureStyle.randomDetailsPattern.Stretch(longitudeInTiles, heightInTiles); Pattern <FacadeOperation> operationsPattern; if (architectureStyle.usesOperations) { operationsPattern = architectureStyle.randomOperationsPattern.Stretch(longitudeInTiles, heightInTiles); } else { operationsPattern = null; } PatternEvaluator.Evaluate(elementsPattern, detailsPattern, operationsPattern, architectureStyle); facades [i++] = new Facade(freeFace, longitude, height, longitudeInTiles, heightInTiles, architectureStyle, elementsPattern, detailsPattern, operationsPattern); } _buildings.Add(new Building(allotment.x, allotment.y, width, height, depth, widthInTiles, heightInTiles, depthInTiles, facades, architectureStyle)); } }
public static Pattern <T>[] ParsePatterns <T> (TextAsset patternsFile, ArchitectureStyle architectureStyle) where T : IPatternItem, new() { string[] patternsStrings = Regex.Split(patternsFile.text, @"\-"); Pattern <T>[] patterns = new Pattern <T> [patternsStrings.Length]; for (int i = 0; i < patterns.Length; i++) { string patternString = patternsStrings [i].Trim(); if (patternString.Length == 0) { continue; } patterns [i] = ParsePattern <T> (patternString, architectureStyle); } return(patterns); }
public Building(int x, int y, int width, int height, int depth, int widthInTiles, int heightInTiles, int depthInTiles, Facade[] facades, ArchitectureStyle architecturalStyle) { this.x = x; this.y = y; this.width = width; this.height = height; this.depth = depth; this.widthInTiles = widthInTiles; this.heightInTiles = heightInTiles; this.depthInTiles = depthInTiles; this.architectureStyle = architecturalStyle; for (int i = 0; i < facades.Length; i++) { _facades.Add(facades [i].direction, facades [i]); } }
public void Initialize(char symbol, int index, ArchitectureStyle architectureStyle) { this._symbol = symbol; this._index = index; }
public override void Execute(BaseGrid grid, ArchitectureStyle[] allArchitectureStyles, int[] architectureStylesMap, List <Block> blocks) { _allotments = new List <Allotment> (); foreach (Block block in blocks) { List <Rect> allPossibleAreas = new List <Rect> (); foreach (ArchitectureStyle possibleArchitectureStyle in block.architectureStyles) { int tileWidth = possibleArchitectureStyle.tileWidth; Rect[] possibleAreas = Combinatorics.PossibleAreas(possibleArchitectureStyle.minWidth + possibleArchitectureStyle.spacing, possibleArchitectureStyle.maxWidth + possibleArchitectureStyle.spacing, possibleArchitectureStyle.minDepth + possibleArchitectureStyle.spacing, possibleArchitectureStyle.maxDepth + possibleArchitectureStyle.spacing); foreach (Rect possibleArea in possibleAreas) { Rect area = new Rect(0, 0, possibleArea.width * tileWidth, possibleArea.height * tileWidth); if (!allPossibleAreas.Contains(area)) { allPossibleAreas.Add(area); } } } List <Rect> allotmentAreas = new List <Rect> (); MaxRects maxRects = new MaxRects(block.width, block.depth); if (_tryToFitSmallerAllotmentsFirst) { // sort possible allotment areas by rectangle area allPossibleAreas.Sort(delegate(Rect r1, Rect r2) { float a1 = (r1.width * r1.height); float a2 = (r2.width * r2.height); return(a1.CompareTo(a2)); }); } while (allPossibleAreas.Count > 0) { Rect possibleArea; if (_tryToFitSmallerAllotmentsFirst) { possibleArea = allPossibleAreas [0]; } else { possibleArea = allPossibleAreas [UnityEngine.Random.Range(0, allPossibleAreas.Count)]; } Rect allotmentArea = maxRects.Insert((int)possibleArea.width, (int)possibleArea.height, _allotmentFittingHeuristics); if (allotmentArea.width == 0 || allotmentArea.height == 0) { allPossibleAreas.Remove(possibleArea); continue; } allotmentAreas.Add(new Rect(allotmentArea.x, allotmentArea.y, allotmentArea.width, allotmentArea.height)); } if (maxRects.Occupancy() < _minOccupancyRate) { string message = "block occupancy is less than minimum: " + maxRects.Occupancy(); if (_abortInError) { throw new Exception(message); } else { Debug.LogWarning(message); } } int blockXStart = (int)block.center.x - block.width / 2; int blockZStart = (int)block.center.y - block.depth / 2; foreach (Rect allotmentArea in allotmentAreas) { ArchitectureStyle architectureStyle = FindSuitableArchitectureStyle(allotmentArea, block.architectureStyles); bool hasLeftNeighbour = false; bool hasRightNeighbour = false; bool hasUpperNeighbour = false; bool hasLowerNeighbour = false; foreach (Rect neighbourAllotmentArea in allotmentAreas) { if (neighbourAllotmentArea == allotmentArea) { continue; } if (neighbourAllotmentArea.xMax <= allotmentArea.xMin && ((neighbourAllotmentArea.yMin >= allotmentArea.yMin && neighbourAllotmentArea.yMin <= allotmentArea.yMax) || (neighbourAllotmentArea.yMax >= allotmentArea.yMin && neighbourAllotmentArea.yMax <= allotmentArea.yMax) || (allotmentArea.yMin >= neighbourAllotmentArea.yMin && allotmentArea.yMin <= neighbourAllotmentArea.yMax) || (allotmentArea.yMax >= neighbourAllotmentArea.yMin && allotmentArea.yMax <= neighbourAllotmentArea.yMax))) { hasLeftNeighbour = true; } else if (neighbourAllotmentArea.xMin >= allotmentArea.xMax && ((neighbourAllotmentArea.yMin >= allotmentArea.yMin && neighbourAllotmentArea.yMin <= allotmentArea.yMax) || (neighbourAllotmentArea.yMax >= allotmentArea.yMin && neighbourAllotmentArea.yMax <= allotmentArea.yMax) || (allotmentArea.yMin >= neighbourAllotmentArea.yMin && allotmentArea.yMin <= neighbourAllotmentArea.yMax) || (allotmentArea.yMax >= neighbourAllotmentArea.yMin && allotmentArea.yMax <= neighbourAllotmentArea.yMax))) { hasRightNeighbour = true; } else if (neighbourAllotmentArea.yMin >= allotmentArea.yMax && ((neighbourAllotmentArea.xMin >= allotmentArea.xMin && neighbourAllotmentArea.xMin <= allotmentArea.xMax) || (neighbourAllotmentArea.xMax >= allotmentArea.xMin && neighbourAllotmentArea.xMax <= allotmentArea.xMax) || (allotmentArea.xMin >= neighbourAllotmentArea.xMin && allotmentArea.xMin <= neighbourAllotmentArea.xMax) || (allotmentArea.xMax >= neighbourAllotmentArea.xMin && allotmentArea.xMax <= neighbourAllotmentArea.xMax))) { hasUpperNeighbour = true; } else if (neighbourAllotmentArea.yMax <= allotmentArea.yMin && ((neighbourAllotmentArea.xMin >= allotmentArea.xMin && neighbourAllotmentArea.xMin <= allotmentArea.xMax) || (neighbourAllotmentArea.xMax >= allotmentArea.xMin && neighbourAllotmentArea.xMax <= allotmentArea.xMax) || (allotmentArea.xMin >= neighbourAllotmentArea.xMin && allotmentArea.xMin <= neighbourAllotmentArea.xMax) || (allotmentArea.xMax >= neighbourAllotmentArea.xMin && allotmentArea.xMax <= neighbourAllotmentArea.xMax))) { hasLowerNeighbour = true; } } if (hasLeftNeighbour && hasRightNeighbour && hasUpperNeighbour && hasLowerNeighbour) { continue; } List <Direction> freeFaces = new List <Direction> (); if (!hasLowerNeighbour) { freeFaces.Add(Direction.FRONT); } if (!hasUpperNeighbour) { freeFaces.Add(Direction.BACK); } if (!hasLeftNeighbour) { freeFaces.Add(Direction.LEFT); } if (!hasRightNeighbour) { freeFaces.Add(Direction.RIGHT); } int widthInTiles = (int)allotmentArea.width / architectureStyle.tileWidth; int depthInTiles = (int)allotmentArea.height / architectureStyle.tileWidth; int spacing = architectureStyle.spacing * (architectureStyle.tileWidth / 2); _allotments.Add(new Allotment(blockXStart + (int)allotmentArea.x + spacing, blockZStart + (int)allotmentArea.y + spacing, (int)allotmentArea.width, (int)allotmentArea.height, widthInTiles, depthInTiles, freeFaces.ToArray(), architectureStyle)); } } }
public static void Evaluate(Pattern <FacadeItem> elementsPattern, Pattern <FacadeItem> detailsPattern, Pattern <FacadeOperation> operationsPattern, ArchitectureStyle architectureStyle) { if (elementsPattern.width != detailsPattern.width || (operationsPattern != null && elementsPattern.width != operationsPattern.width) || elementsPattern.height != detailsPattern.height || (operationsPattern != null && elementsPattern.height != operationsPattern.height)) { throw new Exception("patterns do not match in size"); } int width = elementsPattern.width; int height = elementsPattern.height; for (int y = 0; y < height; y++) { IModel previousElementModel = null; int x2 = 0; for (int x1 = 0; x1 < width; x1++) { FacadeItem element = elementsPattern.GetElement(x1, y); if (element.invalid) { continue; } if (element.model != previousElementModel) { x2 = x1; } previousElementModel = element.model; if (architectureStyle.groundFloor == GroundFloor.FIRST_FLOOR_FOOTER && y == height - 1) { element.BottomVariant(); } else if (/*architectureStyle.header &&*/ y == 0) { element.TopVariant(); } if (element.size > 1) { // pattern occurring outside its frequency (i.e.: occurrence of a 2 sized pattern in an odd frequency) if ((x1 - x2) % element.size != 0) { element.Invalidate(); detailsPattern.SetElement(x1, y, 'e', 0); continue; } // pattern overflowing other patterns bool substituted = false; for (int i = 1; i < element.size && (i + x1) < width; i++) { FacadeItem neighbourElement = elementsPattern.GetElement(x1 + i, y); // cannot compare neighbour to possibly "transformed" element, so compare to previous element model if (neighbourElement.model != previousElementModel) { elementsPattern.SetElement(x1, y, architectureStyle.defaultFacadeElementSymbol, architectureStyle.defaultFacadeElementIndex); detailsPattern.SetElement(x1, y, architectureStyle.defaultFacadeDetailSymbol, architectureStyle.defaultFacadeDetailIndex); substituted = true; break; } } if (substituted) { for (int i = 1; i < element.size && (i + x1) < width; i++) { elementsPattern.SetElement(x1 + i, y, architectureStyle.defaultFacadeElementSymbol, architectureStyle.defaultFacadeElementIndex); detailsPattern.SetElement(x1 + i, y, architectureStyle.defaultFacadeDetailSymbol, architectureStyle.defaultFacadeDetailIndex); } continue; } } // facade item overflowing the facade if (x1 + element.size > width) { elementsPattern.SetElement(x1, y, architectureStyle.defaultFacadeElementSymbol, architectureStyle.defaultFacadeElementIndex); detailsPattern.SetElement(x1, y, architectureStyle.defaultFacadeDetailSymbol, architectureStyle.defaultFacadeDetailIndex); continue; } if (operationsPattern != null) { // facade item spreading among different elevation levels FacadeOperation operation = operationsPattern.GetElement(x1, y); bool substituted = false; for (int i = 1; i < element.size && (i + x1) < width; i++) { FacadeOperation neighbourOperation = operationsPattern.GetElement(x1 + i, y); if (neighbourOperation != operation) { elementsPattern.SetElement(x1, y, architectureStyle.defaultFacadeElementSymbol, architectureStyle.defaultFacadeElementIndex); detailsPattern.SetElement(x1, y, architectureStyle.defaultFacadeDetailSymbol, architectureStyle.defaultFacadeDetailIndex); substituted = true; } } if (substituted) { for (int i = 1; i < element.size && (i + x1) < width; i++) { elementsPattern.SetElement(x1 + i, y, architectureStyle.defaultFacadeElementSymbol, architectureStyle.defaultFacadeElementIndex); detailsPattern.SetElement(x1 + i, y, architectureStyle.defaultFacadeDetailSymbol, architectureStyle.defaultFacadeDetailIndex); } continue; } } if (!element.allowsDetail) { detailsPattern.SetElement(x1, y, 'e', 0); } } } }
public override void Execute(BaseGrid grid, ArchitectureStyle[] allArchitectureStyles, int[] architectureStylesMap, List <Block> blocks) { _allotments = new List <Allotment> (); foreach (Block block in blocks) { ArchitectureStyle architectureStyle = block.randomArchitectureStyle; int blockWidthInTiles = block.width / architectureStyle.tileWidth; int blockDepthInTiles = block.depth / architectureStyle.tileWidth; int[][] possibleWidths = SubsetSum.Combinations(Enumerable.Range(architectureStyle.minWidth + architectureStyle.spacing, architectureStyle.maxWidth + architectureStyle.spacing).ToArray(), blockWidthInTiles); int[][] possibleDepths = SubsetSum.Combinations(Enumerable.Range(architectureStyle.minDepth + architectureStyle.spacing, architectureStyle.maxDepth + architectureStyle.spacing).ToArray(), blockDepthInTiles); int[] widths = possibleWidths [UnityEngine.Random.Range(0, possibleWidths.Length)]; int[] depths = possibleDepths [UnityEngine.Random.Range(0, possibleDepths.Length)]; int startX = (int)block.center.x - block.width / 2; int startZ = (int)block.center.y - block.depth / 2; int zOffset = 0; for (int z2 = 0; z2 < depths.Length; z2++) { int xOffset = 0; int depthInTiles = depths [z2]; int depth = depthInTiles * architectureStyle.tileWidth; for (int x2 = 0; x2 < widths.Length; x2++) { int widthInTiles = widths [x2]; int width = widthInTiles * architectureStyle.tileWidth; if ((z2 == 0 || z2 == depths.Length - 1) || (x2 == 0 || x2 == widths.Length - 1)) { HashSet <Direction> freeFaces = new HashSet <Direction> (); if (z2 == 0) { freeFaces.Add(Direction.FRONT); } else if (z2 == depths.Length - 1) { freeFaces.Add(Direction.BACK); } if (x2 == 0) { freeFaces.Add(Direction.LEFT); } else if (x2 == widths.Length - 1) { freeFaces.Add(Direction.RIGHT); } _allotments.Add(new Allotment(startX + xOffset, startZ + zOffset, width, depth, widthInTiles, depthInTiles, freeFaces.ToArray(), architectureStyle)); } xOffset += width; } zOffset += depth; } } }