コード例 #1
0
        public void MaxRectsFreeRectanglePostProcessorTestSingleIntersectionInCorner()
        {
            //Arrange
            var postProcessor = new MaxRectsFreeRectanglePostProcessor();
            var freeRects     = new List <PPRect>()
            {
                new PPRect(0, 0, 50, 50),
                new PPRect(50, 0, 100, 50)
            };
            var rectJustPlaced = new PPRect(0, 0, 20, 20);

            //Act
            postProcessor.PostProcess(freeRects, rectJustPlaced);

            //Assert
            Assert.AreEqual(3, freeRects.Count);
            var sortedList = freeRects.OrderBy(x => x.Left).ThenBy(x => x.Top).ToList();

            Assert.AreEqual(sortedList[0].Left, 0);
            Assert.AreEqual(sortedList[0].Top, 20);
            Assert.AreEqual(sortedList[0].Width, 50);
            Assert.AreEqual(sortedList[0].Height, 30);
            Assert.AreEqual(sortedList[1].Left, 20);
            Assert.AreEqual(sortedList[1].Top, 0);
            Assert.AreEqual(sortedList[1].Width, 30);
            Assert.AreEqual(sortedList[1].Height, 50);
            Assert.AreEqual(sortedList[2].Left, 50);
            Assert.AreEqual(sortedList[2].Top, 0);
            Assert.AreEqual(sortedList[2].Width, 50);
            Assert.AreEqual(sortedList[2].Height, 50);
        }
コード例 #2
0
        public void MaxRectsFreeRectangleSortedMergerTestMergeSimple()
        {
            //Arrange
            var freeRectangles = new List <PPRect>()
            {
                new PPRect(0, 0, 10, 12),
                new PPRect(0, 0, 10, 13),
                new PPRect(0, 0, 1000, 200)
            };

            var merger    = new MaxRectsFreeRectangleSortedMerger();
            var freeRect1 = new PPRect(0, 0, 10, 14);
            var freeRect2 = new PPRect(0, 0, 1000, 201);
            var oldSize   = freeRectangles.Count;

            //Act
            merger.MergeFreeRectangles(freeRectangles, new PPRect[] { freeRect1, freeRect2 });

            //Assert
            Assert.AreEqual(oldSize + 2, freeRectangles.Count);
            Assert.AreEqual(10, freeRectangles[0].Width);
            Assert.AreEqual(12, freeRectangles[0].Height);
            Assert.AreEqual(10, freeRectangles[1].Width);
            Assert.AreEqual(13, freeRectangles[1].Height);
            Assert.AreEqual(10, freeRectangles[2].Width);
            Assert.AreEqual(14, freeRectangles[2].Height);
            Assert.AreEqual(1000, freeRectangles[3].Width);
            Assert.AreEqual(200, freeRectangles[3].Height);
            Assert.AreEqual(1000, freeRectangles[4].Width);
            Assert.AreEqual(201, freeRectangles[4].Height);
        }
コード例 #3
0
ファイル: BLAlgorithm.cs プロジェクト: pdokoupil/PaunPacker
        /// <summary>
        /// Tries to improve (decrease its area) the current minimum bounding box
        /// </summary>
        /// <param name="currentRect"></param>
        /// <param name="possibleIntersections"></param>
        /// <param name="direction">0 for try to move up, 1 for try to move left</param>
        /// <returns></returns>
        private bool TryImprove(ref PPRect currentRect, IEnumerable <PPRect> possibleIntersections, int direction)
        {
            //adjust the improvemet to improve by higher steps (using bin search ?)
            bool   ret    = false;
            PPRect toTest = currentRect;

            if (direction == 0)
            {
                toTest.Top--;
                while (toTest.Top >= 0 && !Intersects(toTest, possibleIntersections))
                {
                    toTest.Top--;
                    ret = true;
                }
                toTest.Top++;
            }
            else
            {
                toTest.Left--;
                while (toTest.Left >= 0 && !Intersects(toTest, possibleIntersections))
                {
                    toTest.Left--;
                    ret = true;
                }
                toTest.Left++;
            }
            currentRect = toTest;
            if (ret)
            {
                TryImprove(ref currentRect, possibleIntersections, (direction + 1) % 2);
            }

            return(ret);
        }
コード例 #4
0
        public void BestAreaFitFreeRectangleExtractorTestFitMany()
        {
            //Arrange
            var rects = new List <PPRect>()
            {
                new PPRect(0, 0, 32, 16),
                new PPRect(0, 0, 66, 65),
                new PPRect(0, 0, 65, 65),
                new PPRect(0, 0, 65, 65),
                new PPRect(0, 0, 32, 160),
                new PPRect(0, 0, 320, 16),
            };

            var currentRect = new PPRect(0, 0, 64, 65);
            var extractor   = new BestAreaFitFreeRectangleExtractor();

            //Act
            var result = extractor.ExtractFreeRectangle(rects, currentRect);

            //Assert
            Assert.AreNotEqual(null, result);
            Assert.AreEqual(65, result.Value.Width);
            Assert.AreEqual(65, result.Value.Height);
            Assert.AreEqual(0, result.Value.Left);
            Assert.AreEqual(0, result.Value.Top);
        }
コード例 #5
0
        public void BestAreaFitFreeRectangleExtractorTestFitMany2()
        {
            //Arrange
            var rects = new List <PPRect>()
            {
                new PPRect(7, 6, 7 + 32, 6 + 16),
                new PPRect(6, 1, 6 + 66, 1 + 65),
                new PPRect(14, 89, 14 + 65, 89 + 65),
                new PPRect(31, 124, 31 + 65, 124 + 65),
                new PPRect(89, 13, 89 + 32, 13 + 160),
                new PPRect(78, 500, 78 + 320, 500 + 16),
            };

            var currentRect = new PPRect(0, 0, 64, 65);
            var extractor   = new BestAreaFitFreeRectangleExtractor();

            //Act
            var result = extractor.ExtractFreeRectangle(rects, currentRect);

            //Assert
            Assert.AreNotEqual(null, result);
            Assert.AreEqual(65, result.Value.Width);
            Assert.AreEqual(65, result.Value.Height);
            Assert.IsTrue(14 == result.Value.Left || result.Value.Left == 31);
            Assert.IsTrue(89 == result.Value.Top || result.Value.Left == 124);
        }
コード例 #6
0
        /// <summary>
        /// Performs a split of <paramref name="freeRectangle"/> by a vertical axis
        /// </summary>
        /// <param name="freeRectangle">The free rectangle that was selected for a placement of rectangle to be placed</param>
        /// <param name="justPlacedRect">The rectangle that was just placed into <paramref name="freeRectangle"/></param>
        /// <returns></returns>
        private IEnumerable <PPRect> SplitFreeRectangleVertical(ref PPRect freeRectangle, PPRect justPlacedRect)
        {
            int    splitX    = freeRectangle.Left + justPlacedRect.Width;
            PPRect freeRect1 = new PPRect(freeRectangle.Left, freeRectangle.Top + justPlacedRect.Height, splitX, freeRectangle.Bottom);
            PPRect freeRect2 = new PPRect(splitX, freeRectangle.Top, freeRectangle.Right, freeRectangle.Bottom);

            return(new PPRect[] { freeRect1, freeRect2 }.Where(x => x.Width > 0 && x.Height > 0));
        }
コード例 #7
0
        public void BestAreaFitFreeRectangleExtractorTestNull()
        {
            //Arrange
            var extractor   = new BestAreaFitFreeRectangleExtractor();
            var currentRect = new PPRect(0, 0, 32, 32);

            //Act
            extractor.ExtractFreeRectangle(null, currentRect);
        }
コード例 #8
0
        /// <summary>
        /// Utility method for sorted (based on order given by <see cref="PPRectAreaComparer"/>) insertion
        /// </summary>
        /// <param name="list">List of rectangles</param>
        /// <param name="item">Rectangle that should be inserted</param>
        private void SortedInsertion(List <PPRect> list, PPRect item)
        {
            int position = list.BinarySearch(item, new PPRectAreaComparer());

            if (position < 0)
            {
                position = ~position;
            }
            list.Insert(position, item);
        }
コード例 #9
0
        /// <inheritdoc />
        /// <remarks>
        /// Performs the post-processing after placing the rectangle <paramref name="rectJustPlaced"/>
        /// This includes a "repair" of all the free rectangles that intersects with a <paramref name="rectJustPlaced"/> and removal of free rectangles that are fully included in other free rectangle
        /// </remarks>
        /// <exception cref="ArgumentNullException">Is thrown when the <paramref name="freeRectangles"/> is null</exception>
        public void PostProcess(List <PPRect> freeRectangles, PPRect rectJustPlaced)
        {
            if (freeRectangles == null)
            {
                throw new ArgumentNullException($"The {nameof(freeRectangles)} cannot be null");
            }

            List <PPRect> rectsToAdd = new List <PPRect>();

            PPRect[] resultingFreeRects = new PPRect[4];
            for (int i = 0; i < freeRectangles.Count;)
            {
                if (freeRectangles[i].IntersectsWith(rectJustPlaced))
                {
                    //This is very similar to splitting a free rectangle but it is not the same, because this code does not assume (unlike the IFreeRectangleSplitter) that a rectangles are placed into a bottom-left of the free rectangle
                    //Calculate FreeRect \ rectJustPlaced and split it into at most four free rects
                    //make it always four (save NEW's and just set 0 dimension to nonused, then filter these upon addition)
                    resultingFreeRects[0] = new PPRect(freeRectangles[i].Left, freeRectangles[i].Top, rectJustPlaced.Left, freeRectangles[i].Bottom);     //LEFT
                    resultingFreeRects[1] = new PPRect(freeRectangles[i].Left, freeRectangles[i].Top, freeRectangles[i].Right, rectJustPlaced.Top);       //TOP
                    resultingFreeRects[2] = new PPRect(rectJustPlaced.Right, freeRectangles[i].Top, freeRectangles[i].Right, freeRectangles[i].Bottom);   //RIGHT
                    resultingFreeRects[3] = new PPRect(freeRectangles[i].Left, rectJustPlaced.Bottom, freeRectangles[i].Right, freeRectangles[i].Bottom); //BOTTOM

                    //(PPRect freeRect1, PPRect freeRect2) = splitter.SplitFreeRectangle(freeRectangles[i], rectJustPlaced);
                    freeRectangles.RemoveAt(i);
                    //rectsToAdd.Add(freeRect1);
                    //rectsToAdd.Add(freeRect2);
                    rectsToAdd.AddRange(resultingFreeRects.Where(x => x.Width > 0 && x.Height > 0));
                }
                else
                {
                    i++;
                }
            }

            freeRectangles.AddRange(rectsToAdd);

            List <PPRect> rectsToRemove = new List <PPRect>();

            for (int i = 0; i < freeRectangles.Count; i++)
            {
                for (int j = 0; j < freeRectangles.Count; j++)
                {
                    if (i != j && freeRectangles[i].Contains(freeRectangles[j]))
                    {
                        rectsToRemove.Add(freeRectangles[j]);
                    }
                }
            }

            foreach (var toRemove in rectsToRemove)
            {
                freeRectangles.Remove(toRemove);
            }
        }
コード例 #10
0
 /// <summary>
 /// For a given rectangle that is being placed, selets the split direction (axis)
 /// </summary>
 /// <param name="rectToBePlaced">The rectangle that will be placed</param>
 /// <remarks>The direction is determined only be the <paramref name="rectToBePlaced"/> not by a free rectangle where it will be placed</remarks>
 /// <returns>The SplitDirection (the longer axis)</returns>
 private SplitDirection SelectSplitDirection(PPRect rectToBePlaced)
 {
     if (rectToBePlaced.Width > rectToBePlaced.Height)
     {
         return(SplitDirection.HORIZONTAL);
     }
     else
     {
         return(SplitDirection.VERTICAL);
     }
 }
コード例 #11
0
ファイル: BLAlgorithm.cs プロジェクト: pdokoupil/PaunPacker
        //reimplement it using more efficient sweep a line algorithm
        private static bool Intersects(PPRect tested, IEnumerable <PPRect> possibleIntersections)
        {
            foreach (var x in possibleIntersections)
            {
                if (tested.IntersectsWith(x))
                {
                    return(true);
                }
            }

            return(false);
        }
        public void LongerAxisGuillotineFreeRectangleSplitterTestFullBoth()
        {
            //Arrange
            var splitter       = new LongerAxisGuillotineFreeRectangleSplitter();
            var freeRectangle  = new PPRect(0, 0, 100, 100);
            var rectToBePlaced = new PPRect(0, 0, 100, 100);

            //Act
            var result = splitter.SplitFreeRectangle(freeRectangle, rectToBePlaced);

            //Assert
            Assert.AreEqual(0, result.Count());
        }
コード例 #13
0
        public void MaxRectsFreeRectangleSplitterTestFullBoth()
        {
            //Arrange
            var splitter       = new MaxRectsFreeRectangleSplitter();
            var freeRect       = new PPRect(0, 0, 100, 100);
            var rectJustPlaced = new PPRect(0, 0, 100, 100);

            //Act
            var result = splitter.SplitFreeRectangle(freeRect, rectJustPlaced);

            //Assert
            Assert.AreEqual(0, result.Count());
        }
コード例 #14
0
        public void BestAreaFitFreeRectangleExtractorTestEmpty()
        {
            //Arrange
            var rects       = Enumerable.Empty <PPRect>().ToList();
            var currentRect = new PPRect(0, 0, 32, 32);
            var extractor   = new BestAreaFitFreeRectangleExtractor();

            //Act
            var result = extractor.ExtractFreeRectangle(rects, currentRect);

            //Assert
            Assert.AreEqual(null, result);
        }
コード例 #15
0
        public void BestAreaFitFreeRectangleExtractorTestFitNone()
        {
            //Arrange
            var rects       = Enumerable.Repeat(new PPRect(0, 0, 64, 64), 16).ToList();
            var currentRect = new PPRect(0, 0, 64, 65);
            var extractor   = new BestAreaFitFreeRectangleExtractor();

            //Act
            var result = extractor.ExtractFreeRectangle(rects, currentRect);

            //Assert
            Assert.AreEqual(null, result);
        }
        public void LongerAxisGuillotineFreeRectangleSplitterTestPositionHasNoEffect()
        {
            //Arrange
            var splitter       = new LongerAxisGuillotineFreeRectangleSplitter();
            var freeRectangle  = new PPRect(0, 0, 100, 100);
            var freeRectangle2 = new PPRect(76, 54, 76 + 100, 54 + 100);
            var freeRectangle3 = new PPRect(220, 11, 220 + 100, 11 + 100);
            var rectToBePlaced = new PPRect(0, 0, 50, 50);

            //Act
            var result  = splitter.SplitFreeRectangle(freeRectangle, rectToBePlaced);
            var result2 = splitter.SplitFreeRectangle(freeRectangle2, rectToBePlaced);
            var result3 = splitter.SplitFreeRectangle(freeRectangle3, rectToBePlaced);

            //Assert
            Assert.AreEqual(2, result.Count());
            var item1 = result.First();
            var item2 = result.Skip(1).First();

            Assert.AreEqual(50, item1.Width);
            Assert.AreEqual(50, item2.Width);
            Assert.IsTrue(item1.Height == 50 || item1.Height == 100);
            if (item1.Height == 50)
            {
                //Then the second must have 100
                Assert.AreEqual(100, item2.Height);
            }
            else
            {
                Assert.AreEqual(50, item2.Height);
            }

            Assert.AreEqual(2, result3.Count());
            item1 = result2.First();
            item2 = result2.Skip(1).First();
            Assert.AreEqual(item1.Width, item1.Width);
            Assert.AreEqual(item1.Height, item1.Height);
            Assert.AreEqual(item2.Width, item2.Width);
            Assert.AreEqual(item2.Height, item2.Height);

            Assert.AreEqual(2, result3.Count());
            item1 = result3.First();
            item2 = result3.Skip(1).First();
            Assert.AreEqual(item1.Width, item1.Width);
            Assert.AreEqual(item1.Height, item1.Height);
            Assert.AreEqual(item2.Width, item2.Width);
            Assert.AreEqual(item2.Height, item2.Height);
        }
コード例 #17
0
        public void MaxRectsFreeRectanglePostProcessorTestSingleIntersectionExactFit()
        {
            //Arrange
            var postProcessor = new MaxRectsFreeRectanglePostProcessor();
            var freeRects     = new List <PPRect>()
            {
                new PPRect(0, 0, 100, 100)
            };
            var rectJustPlaced = new PPRect(0, 0, 100, 100);

            //Act
            postProcessor.PostProcess(freeRects, rectJustPlaced);

            //Assert
            Assert.AreEqual(0, freeRects.Count);
        }
コード例 #18
0
        /// <inheritdoc />
        /// <summary>
        /// Split the <paramref name="selectedFreeRectangle"/> by it's longer axis
        /// </summary>
        /// <param name="selectedFreeRectangle">The free rectangle that was selected for a placement of <paramref name="rectToBePlaced"/></param>
        /// <param name="rectToBePlaced">The rectangle that should be placed</param>
        /// <returns>Free rectangle that results from the splitting of <paramref name="selectedFreeRectangle"/></returns>
        public IEnumerable <PPRect> SplitFreeRectangle(PPRect selectedFreeRectangle, PPRect rectToBePlaced)
        {
            SplitDirection splitDirection = SelectSplitDirection(/*selectedFreeRectangle, */ rectToBePlaced);

            switch (splitDirection)
            {
            case SplitDirection.HORIZONTAL:
                return(SplitFreeRectangleHorizontal(ref selectedFreeRectangle, rectToBePlaced));

            case SplitDirection.VERTICAL:
                return(SplitFreeRectangleVertical(ref selectedFreeRectangle, rectToBePlaced));

            default:
                throw new InvalidOperationException();
            }
        }
コード例 #19
0
        public void MaxRectsFreeRectangleSortedMergerTestMergeOneHasZeroSize()
        {
            //Arrange
            var freeRectangles = new List <PPRect>();
            var merger         = new MaxRectsFreeRectangleSortedMerger();
            var freeRect1      = new PPRect(0, 0, 100, 20);
            var freeRect2      = new PPRect(0, 0, 100, 0);
            var oldSize        = freeRectangles.Count;

            //Act
            merger.MergeFreeRectangles(freeRectangles, new PPRect[] { freeRect1, freeRect2 });

            //Assert
            Assert.AreEqual(oldSize + 1, freeRectangles.Count);
            Assert.AreEqual(100, freeRectangles[0].Width);
            Assert.AreEqual(20, freeRectangles[0].Height);
        }
        public void LongerAxisGuillotineFreeRectangleSplitterTestFullHeight()
        {
            //Arrange
            var splitter       = new LongerAxisGuillotineFreeRectangleSplitter();
            var freeRectangle  = new PPRect(0, 0, 200, 100);
            var rectToBePlaced = new PPRect(0, 0, 20, 100);

            //Act
            var result = splitter.SplitFreeRectangle(freeRectangle, rectToBePlaced);

            //Assert
            Assert.AreEqual(1, result.Count());
            var item1 = result.First();

            Assert.AreEqual(180, item1.Width);
            Assert.AreEqual(100, item1.Height);
        }
コード例 #21
0
        public void MaxRectsFreeRectangleSplitterTestFullHeight()
        {
            //Arrange
            var splitter          = new MaxRectsFreeRectangleSplitter();
            var freeRect          = new PPRect(0, 0, 100, 100);
            var rectJustPlaced    = new PPRect(0, 0, 50, 100);
            var expectedFreeRects = new List <PPRect>()
            {
                new PPRect(50, 0, 100, 100)
            };

            //Act
            var result = splitter.SplitFreeRectangle(freeRect, rectJustPlaced);

            //Assert
            CollectionAssert.AreEquivalent(expectedFreeRects, result.ToList());
        }
コード例 #22
0
        /// <inheritdoc />
        /// <summary>
        /// Splits a free rectangle by both vertical and horizontal axis
        /// </summary>
        /// <param name="freeRect">Free rectangle that should be splitted</param>
        /// <param name="rectJustPlaced">The rectangle that should be placed to the <paramref name="freeRect"/></param>
        /// <returns></returns>
        public IEnumerable <PPRect> SplitFreeRectangle(PPRect freeRect, PPRect rectJustPlaced)
        {
            int splitX = freeRect.Left + rectJustPlaced.Width;
            int splitY = freeRect.Top + rectJustPlaced.Height;
            //Perform the split by horizontal axis
            //Rect above the horizontal axis
            var freeRectAbove = new PPRect(freeRect.Left, splitY, freeRect.Right, freeRect.Bottom);
            //Rect below the horizontal axis
            var freeRectBelow = new PPRect(freeRect.Left + rectJustPlaced.Width, freeRect.Top, freeRect.Right, splitY);

            //Perform the split by vertical axis
            //Rect to the right of the vertical axis
            var freeRectRight = new PPRect(splitX, freeRect.Top, freeRect.Right, freeRect.Bottom);
            //Rect to the left of the vertical axis
            var freeRectLeft = new PPRect(freeRect.Left, freeRect.Top + rectJustPlaced.Height, splitX, freeRect.Bottom);

            return(new PPRect[] { freeRectAbove, freeRectRight, freeRectBelow, freeRectLeft }.Where(x => x.Width > 0 && x.Height > 0).Distinct());
        }
        public void LongerAxisGuillotineFreeRectangleSplitterTestSplitByVerticalAxis()
        {
            //Arrange
            var splitter       = new LongerAxisGuillotineFreeRectangleSplitter();
            var freeRectangle  = new PPRect(0, 0, 100, 200);
            var rectToBePlaced = new PPRect(0, 0, 10, 20);

            //Act
            var result = splitter.SplitFreeRectangle(freeRectangle, rectToBePlaced);

            //Assert
            Assert.AreEqual(2, result.Count());
            var item1 = result.First();
            var item2 = result.Skip(1).First();

            Assert.IsTrue((item1.Height == 180 && item1.Width == 10 && item2.Height == 200 && item2.Width == 90) ||
                          (item2.Height == 180 && item2.Width == 10 && item1.Height == 200 && item1.Width == 90));
        }
コード例 #24
0
        /// <summary>
        /// Selects free rectangle from freeLists.
        /// For BestAreaFit it means to select free rectangle of smallest area to which currentRectToPack can fit
        /// </summary>
        /// <param name="freeRects">Free rectangles</param>
        /// <param name="currentRectToPack">Rectangle that will be placed to the selected rectangle</param>
        /// <exception cref="ArgumentNullException">Is thrown when the <paramref name="freeRects"/> is null</exception>
        /// <returns>The best rectangle from <paramref name="freeRects"/> where the <paramref name="currentRectToPack"/> could be placed</returns>
        public PPRect?ExtractFreeRectangle(List <PPRect> freeRects, PPRect currentRectToPack)
        {
            if (freeRects == null)
            {
                throw new ArgumentNullException($"The {nameof(freeRects)} cannot be null");
            }

            PPRect selectedRect = freeRects
                                  .OrderBy(x => ((long)x.Width * x.Height) - ((long)currentRectToPack.Width) * currentRectToPack.Height)
                                  .FirstOrDefault(x => x.Width >= currentRectToPack.Width && x.Height >= currentRectToPack.Height);


            if (selectedRect == null || selectedRect.Width <= 0 || selectedRect.Height <= 0)
            {
                return(null);
            }

            freeRects.Remove(selectedRect);
            return(selectedRect);
        }
コード例 #25
0
        void FlushPixelBuffer()
        {
            if (!IsContextValid)
            {
                return;
            }

            // Note that the pixel lock is held while the buffer is copied into the
            // device context and then flushed.
            PPRect srcRect = new PPRect(Size);

            graphics2DContext.PaintImageData(pixelBuffer, PPPoint.Zero, srcRect);

            if (FlushPending)
            {
                return;
            }

            FlushPending = true;

            graphics2DContext.Flush();
        }
コード例 #26
0
        public void MaxRectsFreeRectanglePostProcessorTestMultiIntersection()
        {
            //Arrange
            var postProcessor = new MaxRectsFreeRectanglePostProcessor();
            var freeRects     = new List <PPRect>()
            {
                new PPRect(0, 0, 50, 50),
                new PPRect(40, 40, 40 + 50, 40 + 50)
            };
            var rectJustPlaced = new PPRect(40, 40, 50, 50);

            //Act
            postProcessor.PostProcess(freeRects, rectJustPlaced);

            //Assert
            Assert.AreEqual(4, freeRects.Count);
            var sortedList = freeRects.OrderBy(x => x.Left).ThenBy(x => x.Top).ThenBy(x => x.Right).ToList();

            Assert.AreEqual(0, sortedList[0].Left);
            Assert.AreEqual(0, sortedList[0].Top);
            Assert.AreEqual(40, sortedList[0].Width);
            Assert.AreEqual(50, sortedList[0].Height);

            Assert.AreEqual(0, sortedList[1].Left);
            Assert.AreEqual(0, sortedList[1].Top);
            Assert.AreEqual(50, sortedList[1].Width);
            Assert.AreEqual(40, sortedList[1].Height);

            Assert.AreEqual(40, sortedList[2].Left);
            Assert.AreEqual(50, sortedList[2].Top);
            Assert.AreEqual(50, sortedList[2].Width);
            Assert.AreEqual(40, sortedList[2].Height);

            Assert.AreEqual(50, sortedList[3].Left);
            Assert.AreEqual(40, sortedList[3].Top);
            Assert.AreEqual(40, sortedList[3].Width);
            Assert.AreEqual(50, sortedList[3].Height);
        }
コード例 #27
0
        public void MaxRectsFreeRectanglePostProcessorTestSingleIntersectionInMiddle()
        {
            //Arrange
            var postProcessor = new MaxRectsFreeRectanglePostProcessor();
            var freeRects     = new List <PPRect>()
            {
                new PPRect(0, 0, 50, 50),
                new PPRect(50, 0, 50 + 50, 50)
            };
            var rectJustPlaced = new PPRect(10, 20, 10 + 20, 20 + 20);

            //Act
            postProcessor.PostProcess(freeRects, rectJustPlaced);

            //Assert
            Assert.AreEqual(5, freeRects.Count); //First free rectangle was divided into four parts
            var sortedList = freeRects.OrderBy(x => x.Left).ThenBy(x => x.Top).ThenBy(x => x.Right).ToList();

            Assert.AreEqual(0, sortedList[0].Left);
            Assert.AreEqual(0, sortedList[0].Top);
            Assert.AreEqual(10, sortedList[0].Width);
            Assert.AreEqual(50, sortedList[0].Height);

            Assert.AreEqual(0, sortedList[1].Left);
            Assert.AreEqual(0, sortedList[1].Top);
            Assert.AreEqual(50, sortedList[1].Width);
            Assert.AreEqual(20, sortedList[1].Height);

            Assert.AreEqual(0, sortedList[2].Left);
            Assert.AreEqual(40, sortedList[2].Top);
            Assert.AreEqual(50, sortedList[2].Width);
            Assert.AreEqual(10, sortedList[2].Height);

            Assert.AreEqual(30, sortedList[3].Left);
            Assert.AreEqual(0, sortedList[3].Top);
            Assert.AreEqual(20, sortedList[3].Width);
            Assert.AreEqual(50, sortedList[3].Height);
        }
コード例 #28
0
ファイル: BLAlgorithm.cs プロジェクト: pdokoupil/PaunPacker
        /// <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);
        }
コード例 #29
0
 /// <summary>
 /// Decides the orientation of the rectangle
 /// </summary>
 /// <remarks>
 /// The rectangle could either be rotated by 90 degrees, or not rotated at all
 /// This default orientation does not rotate
 /// </remarks>
 /// <param name="rect">The rect for which the orientation should be selected</param>
 /// <returns>The <paramref name="rect"/>, possibly rotated</returns>
 private PPRect DecideOrientationOfRect(PPRect rect)
 {
     return(rect);
 }
コード例 #30
0
 /// <summary>
 /// Creates a ViewModel for a given <paramref name="rect"/>
 /// </summary>
 /// <param name="rect">The rectangle for which the view model should be created</param>
 public RectangleViewModel(PPRect rect)
 {
     Rectangle = rect;
 }