Esempio n. 1
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");
            }
        }
Esempio n. 2
0
        /// <inheritdoc />
        public PackingResult PlaceRects(int width, int height, IEnumerable <PPRect> rects, CancellationToken token = default)
        {
            Progress = 0;
            if (width < 0 || height < 0)
            {
                throw new ArgumentOutOfRangeException($"The {nameof(width)} and {nameof(height)} should be non-negative");
            }

            var sortedInput = sorter.SortImages(rects);

            int inputSize   = rects.Count();
            int placedRects = 0;

            int actualWidth  = 0;
            int actualHeight = 0;

            RectComparer       rectComparer              = new RectComparer();
            PointComparer      ptComparer                = new PointComparer();
            SortedSet <PPRect> currentPacking            = new SortedSet <PPRect>(rectComparer);
            SortedDictionary <SKPointI, int> pointsToTry = new SortedDictionary <SKPointI, int>(ptComparer)
            {
                { new SKPointI(0, 0), -1 } //the current packing is empty, so only point to try is point [0,0]
            };

            SKPointI[] pointsToAdd = new SKPointI[2];
            foreach (var x in sortedInput)
            {
                if (token.IsCancellationRequested)
                {
                    Progress = 0;
                    return(null);
                }
                SKPointI?pointToRemove = null;
                foreach (var ptToTry in pointsToTry)
                {
                    PPRect tested = new PPRect(ptToTry.Key.X, ptToTry.Key.Y, ptToTry.Key.X + x.Width, ptToTry.Key.Y + x.Height);
                    var    possibleIntersections = currentPacking.AsEnumerable();                                                             //have to test everything
                    if (ptToTry.Key.X + x.Width <= width && ptToTry.Key.Y + x.Height <= height && !Intersects(tested, possibleIntersections)) //safe to pack here
                    {
                        if (ptToTry.Key.X + x.Width > actualWidth)
                        {
                            actualWidth = ptToTry.Key.X + x.Width;
                        }

                        if (ptToTry.Key.Y + x.Height > actualHeight)
                        {
                            actualHeight = ptToTry.Key.Y + x.Height;
                        }

                        int improved = 0;
                        if (TryImprove(ref tested, currentPacking, 0)) //Try to position it further to the top / left
                        {
                            improved++;
                        }

                        //Add it to the packing
                        tested.Image = x.Image;
                        currentPacking.Add(tested);
                        if (improved == 0)
                        {
                            pointToRemove = ptToTry.Key;
                        }

                        pointsToAdd[0] = new SKPointI(ptToTry.Key.X + x.Width, ptToTry.Key.Y);
                        pointsToAdd[1] = new SKPointI(ptToTry.Key.X, ptToTry.Key.Y + x.Height);

                        break;
                    }
                }

                if (pointToRemove != null)
                {
                    pointsToTry.Remove(pointToRemove.Value);
                    pointsToTry[pointsToAdd[0]] = -1;
                    pointsToTry[pointsToAdd[1]] = -1;

                    Progress = (int)((++placedRects / (double)inputSize) * 100.0);
                    ProgressChange?.Invoke(this, Progress);
                }
                else
                {
                    Progress = 100;
                    return(null); //we cannot pack it anywhere
                }
            }


            //var result = new PackingResult(width, height, currentPacking.Select(x => (x.Value, x.Key))); // probably better to return result with actual width & height instead of those needed
            //actual height can be lower than height specified, width also BUT THIS IS NOT DESIRED, BECAUSE THIS CAN BE CALLED FROM FIXEDSIZE..? OR chhange size in FixedSize..
            var result = new PackingResult(actualWidth, actualHeight, currentPacking);

            return(result);
        }