void PackBins()
    {
        MaxRects maxRects = new MaxRects((int)_container.width, (int)_container.height, false);

        _bins = new List <Rect> ();

        if (_tryToFillContainer)
        {
            List <Rect> inputs = new List <Rect> (_items);
            while (inputs.Count > 0)
            {
                Rect input  = inputs [UnityEngine.Random.Range(0, inputs.Count)];
                Rect output = maxRects.Insert((int)input.width, (int)input.height, MaxRects.FreeRectChoiceHeuristic.RectContactPointRule);
                if (IsDegenerate(output))
                {
                    inputs.Remove(input);
                }
                else
                {
                    _bins.Add(new Rect(output.x + _container.x, output.y + _container.y, output.width, output.height));
                }
            }
        }
        else
        {
            foreach (Rect input in _items)
            {
                Rect output = maxRects.Insert((int)input.width, (int)input.height, MaxRects.FreeRectChoiceHeuristic.RectContactPointRule);
                _bins.Add(new Rect(output.x + _container.x, output.y + _container.y, output.width, output.height));
            }
        }
    }
    public static Dictionary <string, Rect> RepackRects(Dictionary <string, Rect> atlasRects1, out int size, int minAtlasSize, int maxAtlasSize)
    {
        MaxRects maxRects;

        size = minAtlasSize;
        Dictionary <string, Rect> atlasRects2 = new Dictionary <string, Rect> ();

        while (true)
        {
            maxRects = new MaxRects(size, size, false);
            bool fit = true;
            atlasRects2.Clear();
            foreach (KeyValuePair <string, Rect> atlasRect1 in atlasRects1)
            {
                Rect atlasRect2 = maxRects.Insert((int)atlasRect1.Value.width, (int)atlasRect1.Value.height, MaxRects.FreeRectChoiceHeuristic.RectBestAreaFit);
                if (atlasRect2.width == 0 || atlasRect2.height == 0)
                {
                    size *= 2;

                    if (size > maxAtlasSize)
                    {
                        throw new Exception("texture atlas bigger than " + maxAtlasSize + "x" + maxAtlasSize);
                    }
                    fit = false;
                    break;
                }
                atlasRects2.Add(atlasRect1.Key, atlasRect2);
            }
            if (fit)
            {
                break;
            }
        }
        return(atlasRects2);
    }
    public static Dictionary <Texture2D, Rect> PackTextures(HashSet <Texture2D> textures, out int size, int minAtlasSize, int maxAtlasSize)
    {
        MaxRects maxRects;

        size = minAtlasSize;
        Dictionary <Texture2D, Rect> atlasRectsPerTexture = new Dictionary <Texture2D, Rect> ();

        while (true)
        {
            maxRects = new MaxRects(size, size, false);
            bool fit = true;
            atlasRectsPerTexture.Clear();
            foreach (Texture2D texture in textures)
            {
                Rect atlasRect = maxRects.Insert(texture.width, texture.height, MaxRects.FreeRectChoiceHeuristic.RectBestAreaFit);
                if (atlasRect.width == 0 || atlasRect.height == 0)
                {
                    size *= 2;

                    if (size > maxAtlasSize)
                    {
                        throw new Exception("texture atlas bigger than " + maxAtlasSize + "x" + maxAtlasSize);
                    }
                    fit = false;
                    break;
                }
                atlasRectsPerTexture.Add(texture, atlasRect);
            }
            if (fit)
            {
                break;
            }
        }
        return(atlasRectsPerTexture);
    }
Example #4
0
        public MaxRectsPacker(Settings settings)
        {
            _settings      = settings;
            _methods       = new List <FreeRectChoiceHeuristic>(Enum.GetValues(typeof(FreeRectChoiceHeuristic)).OfType <FreeRectChoiceHeuristic>());
            _rectCompartor = new RectComparer(this);
            _maxRects      = new MaxRects(this);

            if (_settings.MinWidth > _settings.MaxWidth)
            {
                throw new Exception("Page min width cannot be higher than max width");
            }
            if (_settings.MinHeight > _settings.MaxHeight)
            {
                throw new Exception("Page min height cannot be higher than max height");
            }
        }
Example #5
0
    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));
            }
        }
    }